Package crazypants.render

Source Code of crazypants.render.ConnectedTextureRenderer$TextureCallback

package crazypants.render;

import java.util.ArrayList;
import java.util.List;

import net.minecraft.block.Block;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.util.IIcon;
import net.minecraft.world.IBlockAccess;
import net.minecraftforge.common.util.ForgeDirection;
import crazypants.util.BlockCoord;
import crazypants.util.ForgeDirectionOffsets;
import crazypants.vecmath.Vector2f;
import crazypants.vecmath.Vector3d;
import crazypants.vecmath.Vector4f;
import crazypants.vecmath.Vertex;

public class ConnectedTextureRenderer implements IRenderFace {

  public static interface TextureCallback {
    public IIcon getTextureForFace(ForgeDirection dir);
  }

  public static class DefaultTextureCallback implements TextureCallback {

    private final IIcon tex;

    private final Block block;
    private final int meta;

    public DefaultTextureCallback(IIcon borderTex) {
      this.tex = borderTex;
      block = null;
      meta = 0;
    }

    public DefaultTextureCallback(Block block, int meta) {
      tex = null;
      this.block = block;
      this.meta = meta;
    }

    @Override
    public IIcon getTextureForFace(ForgeDirection dir) {
      if(tex != null) {
        return tex;
      }
      if(block != null) {
        return block.getIcon(dir.ordinal(), meta);
      }
      return null;
    }

  }

  private boolean forceAllEdges = false;

  private TextureCallback edgeTexureCallback;

  private boolean matchMetaData;

  public boolean isForceAllEdges() {
    return forceAllEdges;
  }

  public void setForceAllEdges(boolean forceAllEdges) {
    this.forceAllEdges = forceAllEdges;
  }

  public TextureCallback getEdgeTexureCallback() {
    return edgeTexureCallback;
  }

  public void setEdgeTexureCallback(TextureCallback edgeTexureCallback) {
    this.edgeTexureCallback = edgeTexureCallback;
  }

  public void setEdgeTexture(IIcon texture) {
    if(texture == null) {
      edgeTexureCallback = null;
      return;
    }
    edgeTexureCallback = new DefaultTextureCallback(texture);
  }
 
  public void setMatchMeta(boolean matchMetaData) {
    this.matchMetaData = matchMetaData;       
  }


  @Override
  public void renderFace(CustomRenderBlocks rb, ForgeDirection face, Block par1Block, double x, double y, double z, IIcon texture, List<Vertex> refVertices,
      boolean translateToXYZ) {

    List<Vertex> finalVerts = new ArrayList<Vertex>();
    finalVerts.addAll(refVertices);

    IIcon borderTex = edgeTexureCallback == null ? null : edgeTexureCallback.getTextureForFace(face);
    if(borderTex != null) {

      texture = borderTex;
      List<ForgeDirection> edges;
      if(forceAllEdges) {
        edges = RenderUtil.getEdgesForFace(face);
      } else {
        edges = RenderUtil.getNonConectedEdgesForFace(rb.blockAccess, (int) x, (int) y, (int) z, face, matchMetaData);
      }

      List<ForgeDirection> allEdges = RenderUtil.getEdgesForFace(face);

      float scaleFactor = 15f / 16f;
      Vector2f uv = new Vector2f();

      //for each that needs a border, add a geom for the border and move in the 'centre' of the face
      //so there is no overlap
      for (ForgeDirection edge : edges) {

        //We need to move the 'centre' of the face so it doesn't overlap with the border
        moveCorners(refVertices, edge, 1 - scaleFactor);

        //Now create the geometry for this edge of the border
        float xLen = 1 - Math.abs(edge.offsetX) * scaleFactor;
        float yLen = 1 - Math.abs(edge.offsetY) * scaleFactor;
        float zLen = 1 - Math.abs(edge.offsetZ) * scaleFactor;

        BoundingBox bb = BoundingBox.UNIT_CUBE.scale(xLen, yLen, zLen);

        List<Vector3d> corners = bb.getCornersForFaceD(face);
        for (Vector3d corner : corners) {
          if(translateToXYZ) {
            corner.x += x;
            corner.y += y;
            corner.z += z;
          }
          corner.x += (float) (edge.offsetX * 0.5) - Math.signum(edge.offsetX) * xLen / 2f;
          corner.y += (float) (edge.offsetY * 0.5) - Math.signum(edge.offsetY) * yLen / 2f;
          corner.z += (float) (edge.offsetZ * 0.5) - Math.signum(edge.offsetZ) * zLen / 2f;
        }

        int[] indices = new int[] { 0, 1, 2, 3 };
        for (int index : indices) {
          Vector3d corner = corners.get(index);
          if(translateToXYZ) {
            RenderUtil.getUvForCorner(uv, corner, (int) x, (int) y, (int) z, face, texture);
          } else {
            RenderUtil.getUvForCorner(uv, corner, 0, 0, 0, face, texture);
          }
          Vertex vertex = new Vertex();
          vertex.xyz.set(corner);
          //vertex.xyz.add(ForgeDirectionOffsets.offsetScaled(face, 0.00005));
          vertex.uv = new Vector2f(uv);
          applyLighting(vertex, corner, refVertices);
          finalVerts.add(vertex);
        }
      }

      for (int i = 0; i < allEdges.size(); i++) {
        ForgeDirection dir = allEdges.get(i);
        ForgeDirection dir2 = i + 1 < allEdges.size() ? allEdges.get(i + 1) : allEdges.get(0);
        if(needsCorner(dir, dir2, edges, face, par1Block, x, y, z, rb.blockAccess)) {

          Vertex v = new Vertex();
          v.uv = new Vector2f();
          v.xyz.set(ForgeDirectionOffsets.forDir(dir));
          v.xyz.add(ForgeDirectionOffsets.forDir(dir2));
          //TODO: dodgy hack to just move the corner forward a bit         
          v.xyz.add(ForgeDirectionOffsets.offsetScaled(face, 0.001f));
          v.xyz.x = Math.max(-0.001, v.xyz.x);
          v.xyz.y = Math.max(-0.001, v.xyz.y);
          v.xyz.z = Math.max(-0.001, v.xyz.z);

          if(ForgeDirectionOffsets.isPositiveOffset(face)) {
            v.xyz.add(ForgeDirectionOffsets.forDir(face));
          }

          if(translateToXYZ) {
            v.xyz.x += x;
            v.xyz.y += y;
            v.xyz.z += z;
            RenderUtil.getUvForCorner(v.uv, v.xyz, (int) x, (int) y, (int) z, face, texture);
          } else {
            RenderUtil.getUvForCorner(v.uv, v.xyz, 0, 0, 0, face, texture);
          }
          applyLighting(v, v.xyz, refVertices);

          finalVerts.add(v);

          Vector3d corner = new Vector3d(v.xyz);
          if(ForgeDirectionOffsets.isPositiveOffset(face)) {
            addVertexForCorner(face, x, y, z, texture, translateToXYZ, finalVerts, dir2, null, corner);
            addVertexForCorner(face, x, y, z, texture, translateToXYZ, finalVerts, dir, dir2, corner);
            addVertexForCorner(face, x, y, z, texture, translateToXYZ, finalVerts, dir, null, corner);
          } else {
            addVertexForCorner(face, x, y, z, texture, translateToXYZ, finalVerts, dir, null, corner);
            addVertexForCorner(face, x, y, z, texture, translateToXYZ, finalVerts, dir, dir2, corner);
            addVertexForCorner(face, x, y, z, texture, translateToXYZ, finalVerts, dir2, null, corner);
          }
        }
      }
    }

    RenderUtil.addVerticesToTessellator(finalVerts, Tessellator.instance);
  }

  private Vertex getClosestVertex(List<Vertex> vertices, Vector3d corner) {
    Vertex result = null;
    double d2 = Double.MAX_VALUE;
    for (Vertex v : vertices) {
      double tmp = corner.distanceSquared(v.xyz);
      if(tmp <= d2) {
        result = v;
        d2 = tmp;
      }
    }
    return result;
  }

  private void addVertexForCorner(ForgeDirection face, double x, double y, double z, IIcon texture, boolean translateToXYZ, List<Vertex> vertices,
      ForgeDirection dir, ForgeDirection dir2, Vector3d corner) {
    float scale = 1 / 16f;
    Vertex vert = new Vertex();
    vert.uv = new Vector2f();
    vert.xyz.set(corner);
    vert.xyz.sub(ForgeDirectionOffsets.offsetScaled(dir, scale));
    if(dir2 != null) {
      vert.xyz.sub(ForgeDirectionOffsets.offsetScaled(dir2, scale));
    }
    if(translateToXYZ) {
      RenderUtil.getUvForCorner(vert.uv, vert.xyz, (int) x, (int) y, (int) z, face, texture);
    } else {
      RenderUtil.getUvForCorner(vert.uv, vert.xyz, 0, 0, 0, face, texture);
    }
    applyLighting(vert, corner, vertices);
    vertices.add(vert);
  }

  private void applyLighting(Vertex vert, Vector3d samplePoint, List<Vertex> litVertices) {
    Vertex closest = getClosestVertex(litVertices, samplePoint);
    if(closest == null) {
      return;
    }
    vert.setBrightness(closest.brightness);
    Vector4f col = closest.getColor();
    if(col != null) {
      vert.setColor(col);
    }
  }

  private boolean needsCorner(ForgeDirection dir, ForgeDirection dir2, List<ForgeDirection> edges, ForgeDirection face,
      Block par1Block, double x, double y,
      double z, IBlockAccess blockAccess) {

    if(edges.contains(dir) || edges.contains(dir2)) {
      return false;
    }

    BlockCoord bc = new BlockCoord((int) x, (int) y, (int) z);
    BlockCoord testLoc = bc.getLocation(dir);
    if(RenderUtil.getNonConectedEdgesForFace(blockAccess, testLoc.x, testLoc.y, testLoc.z, face).contains(dir2)) {
      return true;
    }
    testLoc = bc.getLocation(dir2);
    if(RenderUtil.getNonConectedEdgesForFace(blockAccess, testLoc.x, testLoc.y, testLoc.z, face).contains(dir)) {
      return true;
    }
    return false;
  }

  private void moveCorners(List<Vertex> vertices, ForgeDirection edge, float scaleFactor) {
    int[] indices = getClosest(edge, vertices);
    if(indices[0] < 0) {
      return;
    }
    vertices.get(indices[0]).xyz.x -= scaleFactor * edge.offsetX;
    vertices.get(indices[1]).xyz.x -= scaleFactor * edge.offsetX;
    vertices.get(indices[0]).xyz.y -= scaleFactor * edge.offsetY;
    vertices.get(indices[1]).xyz.y -= scaleFactor * edge.offsetY;
    vertices.get(indices[0]).xyz.z -= scaleFactor * edge.offsetZ;
    vertices.get(indices[1]).xyz.z -= scaleFactor * edge.offsetZ;
  }

  private int[] getClosest(ForgeDirection edge, List<Vertex> vertices) {
    int[] res = new int[] { -1, -1 };
    boolean highest = edge.offsetX > 0 || edge.offsetY > 0 || edge.offsetZ > 0;
    double minMax = highest ? -Double.MAX_VALUE : Double.MAX_VALUE;
    int index = 0;
    for (Vertex v : vertices) {
      double val = get(v.xyz, edge);
      if(highest ? val >= minMax : val <= minMax) {
        if(val != minMax) {
          res[0] = index;
        } else {
          res[1] = index;
        }
        minMax = val;
      }
      index++;
    }
    return res;
  }

  private double get(Vector3d xyz, ForgeDirection edge) {
    if(edge == ForgeDirection.EAST || edge == ForgeDirection.WEST) {
      return xyz.x;
    }
    if(edge == ForgeDirection.UP || edge == ForgeDirection.DOWN) {
      return xyz.y;
    }
    return xyz.z;
  }

 
}
TOP

Related Classes of crazypants.render.ConnectedTextureRenderer$TextureCallback

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.