Package crazypants.enderio.conduit.geom

Source Code of crazypants.enderio.conduit.geom.ConduitGeometryUtil

package crazypants.enderio.conduit.geom;

import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;

import net.minecraftforge.common.util.ForgeDirection;
import crazypants.enderio.conduit.IConduit;
import crazypants.render.BoundingBox;
import crazypants.util.ForgeDirectionOffsets;
import crazypants.vecmath.VecmathUtil;
import crazypants.vecmath.Vector3d;

public class ConduitGeometryUtil {

  public static final ConduitGeometryUtil instance = new ConduitGeometryUtil();

  public static float STUB_WIDTH = 0.2f;
  public static float STUB_HEIGHT = 0.2f;

  public static float WIDTH;
  public static float HEIGHT;

  public static float HWIDTH;
  public static float HHEIGHT;

  // All values are for a single conduit core
  public static Vector3d CORE_MIN;
  public static Vector3d CORE_MAX;
  public static BoundingBox CORE_BOUNDS;

  public static final float CONNECTOR_DEPTH = 0.05f;

  private static Map<ForgeDirection, BoundingBox[]> EXTERNAL_CONNECTOR_BOUNDS = new HashMap<ForgeDirection, BoundingBox[]>();

  static {
    setupBounds(0.5f);
  }

  public static void setupBounds(float scale) {
    float size = 0.075f + (0.175f * scale);

    WIDTH = size;
    HEIGHT = size;
    HWIDTH = WIDTH / 2;
    HHEIGHT = HEIGHT / 2;

    CORE_MIN = new Vector3d(0.5f - HWIDTH, 0.5 - HHEIGHT, 0.5 - HWIDTH);
    CORE_MAX = new Vector3d(CORE_MIN.x + WIDTH, CORE_MIN.y + HEIGHT, CORE_MIN.z + WIDTH);
    CORE_BOUNDS = new BoundingBox(CORE_MIN, CORE_MAX);

    float connectorWidth = 0.25f + (scale * 0.5f);
    for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
      EXTERNAL_CONNECTOR_BOUNDS.put(dir, createExternalConnector(dir, CONNECTOR_DEPTH, connectorWidth));
    }
  }

  private static BoundingBox[] createExternalConnector(ForgeDirection dir, float connectorDepth, float connectorWidth) {

    BoundingBox[] res = new BoundingBox[2];

    float cMin = 0.5f - connectorWidth / 2;
    float cMax = 0.5f + connectorWidth / 2;
    float dMin = 1 - connectorDepth / 2;
    float dMax = 1;

    res[0] = createConnectorComponent(dir, cMin, cMax, dMin, dMax);

    cMin = 0.5f - connectorWidth / 3;
    cMax = 0.5f + connectorWidth / 3;
    dMin = 1 - connectorDepth;
    dMax = 1 - connectorDepth / 2;

    res[1] = createConnectorComponent(dir, cMin, cMax, dMin, dMax);

    return res;
  }

  private static BoundingBox createConnectorComponent(ForgeDirection dir, float cornerMin, float cornerMax, float depthMin, float depthMax) {
    float minX = (1 - Math.abs(dir.offsetX)) * cornerMin + dir.offsetX * depthMin;
    float minY = (1 - Math.abs(dir.offsetY)) * cornerMin + dir.offsetY * depthMin;
    float minZ = (1 - Math.abs(dir.offsetZ)) * cornerMin + dir.offsetZ * depthMin;

    float maxX = (1 - Math.abs(dir.offsetX)) * cornerMax + (dir.offsetX * depthMax);
    float maxY = (1 - Math.abs(dir.offsetY)) * cornerMax + (dir.offsetY * depthMax);
    float maxZ = (1 - Math.abs(dir.offsetZ)) * cornerMax + (dir.offsetZ * depthMax);

    minX = fix(minX);
    minY = fix(minY);
    minZ = fix(minZ);
    maxX = fix(maxX);
    maxY = fix(maxY);
    maxZ = fix(maxZ);

    BoundingBox bb = new BoundingBox(minX, minY, minZ, maxX, maxY, maxZ);
    bb = bb.fixMinMax();

    return bb;
  }

  private static float fix(float val) {
    return val < 0 ? 1 + val : val;
  }

  private Map<GeometryKey, BoundingBox> boundsCache = new HashMap<GeometryKey, BoundingBox>();

  private EnumMap<ConduitConnectorType, BoundingBox> connectorBounds = new EnumMap<ConduitConnectorType, BoundingBox>(ConduitConnectorType.class);

  private ConduitGeometryUtil() {
  }

  public BoundingBox getExternalConnectorBoundingBox(ForgeDirection dir) {
    return getExternalConnectorBoundingBoxes(dir)[0];
  }

  public BoundingBox[] getExternalConnectorBoundingBoxes(ForgeDirection dir) {
    return EXTERNAL_CONNECTOR_BOUNDS.get(dir);
  }

  public BoundingBox getBoundingBox(Class<? extends IConduit> type, ForgeDirection dir, boolean isStub, Offset offset) {
    GeometryKey key = new GeometryKey(dir, isStub, offset, type);
    BoundingBox result = boundsCache.get(key);
    if(result == null) {
      result = createConduitBounds(type, key);
      boundsCache.put(key, result);
    }
    return result;
  }

  public Vector3d getTranslation(ForgeDirection dir, Offset offset) {
    Vector3d result = new Vector3d(offset.xOffset, offset.yOffset, offset.zOffset);
    result.scale(WIDTH);
    return result;
  }

  public BoundingBox createBoundsForConnectionController(ForgeDirection dir, Offset offset) {

    Vector3d nonUniformScale = ForgeDirectionOffsets.forDirCopy(dir);
    nonUniformScale.scale(0.5);

    nonUniformScale.x = 0.8 * (1 - Math.abs(nonUniformScale.x));
    nonUniformScale.y = 0.8 * (1 - Math.abs(nonUniformScale.y));
    nonUniformScale.z = 0.8 * (1 - Math.abs(nonUniformScale.z));

    BoundingBox bb = CORE_BOUNDS;
    bb = bb.scale(nonUniformScale.x, nonUniformScale.y, nonUniformScale.z);

    double offsetFromEnd = Math.min(bb.sizeX(), bb.sizeY());
    offsetFromEnd = Math.min(offsetFromEnd, bb.sizeZ());
    offsetFromEnd = Math.max(offsetFromEnd, 0.075);
    double transMag = 0.5 - (offsetFromEnd * 1.2);

    Vector3d trans = ForgeDirectionOffsets.forDirCopy(dir);
    trans.scale(transMag);
    bb = bb.translate(trans);
    bb = bb.translate(getTranslation(dir, offset));
    return bb;
  }

  private BoundingBox createConduitBounds(Class<? extends IConduit> type, GeometryKey key) {
    return createConduitBounds(type, key.dir, key.isStub, key.offset);
  }

  private BoundingBox createConduitBounds(Class<? extends IConduit> type, ForgeDirection dir, boolean isStub, Offset offset) {
    BoundingBox bb = CORE_BOUNDS;

    Vector3d min = bb.getMin();
    Vector3d max = bb.getMax();

    switch (dir) {
    case WEST:
      min.x = isStub ? Math.max(0, bb.minX - STUB_WIDTH) : 0;
      max.x = bb.minX;
      break;
    case EAST:
      min.x = bb.maxX;
      max.x = isStub ? Math.min(1, bb.maxX + STUB_WIDTH) : 1;
      break;
    case DOWN:
      min.y = isStub ? Math.max(0, bb.minY - STUB_HEIGHT) : 0;
      max.y = bb.minY;
      break;
    case UP:
      max.y = isStub ? Math.min(1, bb.maxY + STUB_HEIGHT) : 1;
      min.y = bb.maxY;
      break;
    case NORTH:
      min.z = isStub ? Math.max(0.0F, bb.minZ - STUB_WIDTH) : 0;
      max.z = bb.minZ;
      break;
    case SOUTH:
      max.z = isStub ? Math.min(1F, bb.maxZ + STUB_WIDTH) : 1;
      min.z = bb.maxZ;
      break;
    default:
      break;
    }

    Vector3d trans = getTranslation(dir, offset);
    min.add(trans);
    max.add(trans);
    bb = new BoundingBox(VecmathUtil.clamp(min, 0, 1), VecmathUtil.clamp(max, 0, 1));
    return bb;
  }

}
TOP

Related Classes of crazypants.enderio.conduit.geom.ConduitGeometryUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.