Package crazypants.enderio.conduit.render

Source Code of crazypants.enderio.conduit.render.RoundedSegmentRenderer

package crazypants.enderio.conduit.render;

import static crazypants.util.ForgeDirectionOffsets.*;
import static net.minecraftforge.common.util.ForgeDirection.*;

import java.util.List;

import net.minecraft.client.renderer.Tessellator;
import net.minecraftforge.common.util.ForgeDirection;
import crazypants.enderio.conduit.geom.ConduitGeometryUtil;
import crazypants.enderio.conduit.geom.Offsets;
import crazypants.enderio.conduit.geom.Offsets.Axis;
import crazypants.render.BoundingBox;
import crazypants.vecmath.Matrix4d;
import crazypants.vecmath.Vector2f;
import crazypants.vecmath.Vector3d;
import crazypants.vecmath.Vector3f;
import crazypants.vecmath.Vertex;

public class RoundedSegmentRenderer {

  private static final int NUM_VERTICES = 16;
  private static Vertex[][] DIR_COORDS = new Vertex[ForgeDirection.VALID_DIRECTIONS.length][];
  private static Vertex[][] DIR_STUB_COORDS = new Vertex[ForgeDirection.VALID_DIRECTIONS.length][];
  private static Vertex[][] DIR_STUB_CAPS = new Vertex[ForgeDirection.VALID_DIRECTIONS.length][];

  private static final Vector3d REF_TRANS = new Vector3d(0.5, 0.5, 0.5);

  static {
    double circ = ConduitGeometryUtil.WIDTH * 0.7;

    double halfLength = 0.25;
    createDirectionSegments(DIR_COORDS, circ, halfLength);

    halfLength = ConduitGeometryUtil.STUB_WIDTH / 2 + ConduitGeometryUtil.CORE_BOUNDS.sizeX() / 4;
    createDirectionSegments(DIR_STUB_COORDS, circ, halfLength);

    createCaps(DIR_STUB_CAPS, circ, halfLength);

  }

  private static void createDirectionSegments(Vertex[][] segments, double circ, double halfLength) {
    Vertex[] refCoords = createUnitSectionQuads(NUM_VERTICES, -halfLength, halfLength);

    createSegmentsForDirections(segments, circ, halfLength, refCoords);
  }

  private static void createCaps(Vertex[][] segments, double circ, double halfLength) {
    Vertex[] refCrossSection = createUnitCrossSection(0, 0, halfLength, 16, 0);

    Vertex center = new Vertex(new Vector3d(0, 0, halfLength), new Vector3f(0, 0, 1), new Vector2f(0.5f, 0.5f));

    Vertex[] refCoords = new Vertex[refCrossSection.length * 4];
    int index = 0;
    for (int i = 0; i < refCrossSection.length; i++) {
      refCoords[index] = new Vertex(center);
      refCoords[index + 1] = new Vertex(refCrossSection[i]);

      int next = i + 1;
      if(next >= refCrossSection.length - 1) {
        next = 0;
      }
      refCoords[index + 2] = new Vertex(refCrossSection[next]);
      refCoords[index + 3] = new Vertex(center);
      index += 4;
    }

    createSegmentsForDirections(segments, circ, halfLength, refCoords);

  }

  private static void createSegmentsForDirections(Vertex[][] segments, double circ, double halfLength, Vertex[] refCoords) {
    for (Vertex coord : refCoords) {
      coord.xyz.x = coord.xyz.x * circ;
      coord.xyz.y = coord.xyz.y * circ;
    }
    Matrix4d rotMat = new Matrix4d();
    rotMat.setIdentity();
    rotMat.setTranslation(REF_TRANS);

    segments[SOUTH.ordinal()] = xformCoords(refCoords, rotMat, offsetScaled(ForgeDirection.SOUTH, halfLength));

    rotMat.makeRotationY(Math.PI);
    rotMat.setTranslation(REF_TRANS);
    segments[ForgeDirection.NORTH.ordinal()] = xformCoords(refCoords, rotMat, offsetScaled(ForgeDirection.NORTH, halfLength));

    rotMat.makeRotationY(Math.PI / 2);
    rotMat.setTranslation(REF_TRANS);
    segments[ForgeDirection.EAST.ordinal()] = xformCoords(refCoords, rotMat, offsetScaled(ForgeDirection.EAST, halfLength));

    rotMat.makeRotationY(-Math.PI / 2);
    rotMat.setTranslation(REF_TRANS);
    segments[ForgeDirection.WEST.ordinal()] = xformCoords(refCoords, rotMat, offsetScaled(ForgeDirection.WEST, halfLength));

    rotMat.makeRotationX(-Math.PI / 2);
    rotMat.setTranslation(REF_TRANS);
    segments[ForgeDirection.UP.ordinal()] = xformCoords(refCoords, rotMat, offsetScaled(ForgeDirection.UP, halfLength));

    rotMat.makeRotationX(Math.PI / 2);
    rotMat.setTranslation(REF_TRANS);
    segments[ForgeDirection.DOWN.ordinal()] = xformCoords(refCoords, rotMat, offsetScaled(ForgeDirection.DOWN, halfLength));
  }

  private static Vertex[] xformCoords(Vertex[] refCoords, Matrix4d rotMat, Vector3d trans) {
    Vertex[] res = new Vertex[refCoords.length];
    for (int i = 0; i < res.length; i++) {
      res[i] = new Vertex(refCoords[i]);
      res[i].transform(rotMat);
      res[i].translate(trans);
    }
    return res;
  }

  private static Vertex[] xformCoords(List<Vertex> refCoords, Matrix4d rotMat, Vector3d trans) {
    Vertex[] res = new Vertex[refCoords.size()];
    for (int i = 0; i < res.length; i++) {
      res[i] = new Vertex(refCoords.get(i));
      res[i].transform(rotMat);
      res[i].translate(trans);
    }
    return res;
  }

  public static Vertex[] createUnitCrossSection(double xOffset, double yOffset, double zOffset, int numCoords, int u) {

    Vertex[] crossSection = new Vertex[numCoords];

    double angle = 0;
    double inc = (Math.PI * 2) / (crossSection.length - 1);
    for (int i = 0; i < crossSection.length; i++) {
      double x = Math.cos(angle) * 0.5;
      double y = Math.sin(angle) * 0.5;
      angle += inc;
      crossSection[i] = new Vertex();
      crossSection[i].setXYZ(xOffset + x, yOffset + y, zOffset);
      crossSection[i].setNormal(x, y, 0);
      crossSection[i].setUV(u, y + 0.5);
    }
    return crossSection;

  }

  public static void renderSegment(ForgeDirection dir, BoundingBox bounds, float minU, float maxU, float minV, float maxV, boolean isStub) {
    float uScale = maxU - minU;
    float vScale = maxV - minV;

    Vector3d offset = calcOffset(dir, bounds);

    Tessellator tes = Tessellator.instance;
    Vertex[] coords;
    if(isStub) {
      coords = DIR_STUB_COORDS[dir.ordinal()];
    } else {
      coords = DIR_COORDS[dir.ordinal()];
    }

    for (Vertex coord : coords) {
      double u = minU + (coord.uv.x * uScale);
      double v = minV + (coord.uv.y * vScale);
      tes.setNormal(coord.normal.x, coord.normal.y, coord.normal.z);
      tes.addVertexWithUV(offset.x + coord.xyz.x, offset.y + coord.xyz.y, offset.z + coord.xyz.z, u, v);
    }

    if(isStub) {
      coords = DIR_STUB_CAPS[dir.ordinal()];
      for (Vertex coord : coords) {
        double u = minU + (coord.uv.x * uScale);
        double v = minV + (coord.uv.y * vScale);
        tes.setNormal(coord.normal.x, coord.normal.y, coord.normal.z);
        tes.addVertexWithUV(offset.x + coord.xyz.x, offset.y + coord.xyz.y, offset.z + coord.xyz.z, u, v);
      }
    }
  }

  private static Vector3d calcOffset(ForgeDirection dir, BoundingBox bounds) {
    Vector3d res = new Vector3d();
    Vector3d center = bounds.getCenter();
    Axis axis = Offsets.getAxisForDir(dir);
    if(axis == Axis.X) {
      res.set(0, center.y - REF_TRANS.y, center.z - REF_TRANS.z);
    } else if(axis == Axis.Y) {
      res.set(center.x - REF_TRANS.x, 0, center.z - REF_TRANS.z);
    } else if(axis == Axis.Z) {
      res.set(center.x - REF_TRANS.x, center.y - REF_TRANS.y, 0);
    }
    return res;
  }

  public static Vertex[] createUnitSectionQuads(int numCoords, double minZ, double maxZ) {

    Vertex[] z0 = createUnitCrossSection(0, 0, minZ, numCoords + 1, 0);
    Vertex[] z1 = createUnitCrossSection(0, 0, maxZ, numCoords + 1, 1);

    Vertex[] result = new Vertex[numCoords * 4];
    for (int i = 0; i < numCoords; i++) {
      int index = i * 4;
      result[index] = new Vertex(z0[i]);
      result[index + 1] = new Vertex(z0[i + 1]);
      result[index + 2] = new Vertex(z1[i + 1]);
      result[index + 3] = new Vertex(z1[i]);
    }
    return result;

  }

}
TOP

Related Classes of crazypants.enderio.conduit.render.RoundedSegmentRenderer

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.