Files
Chisel/src/main/java/team/chisel/ctmlib/RenderBlocksCTM.java
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

601 lines
24 KiB
Java
Raw Normal View History

2024-02-19 11:13:25 -08:00
package team.chisel.ctmlib;
import static team.chisel.ctmlib.RenderBlocksCTM.SubSide.XNEG_LB;
import static team.chisel.ctmlib.RenderBlocksCTM.SubSide.XNEG_LT;
import static team.chisel.ctmlib.RenderBlocksCTM.SubSide.XNEG_RB;
import static team.chisel.ctmlib.RenderBlocksCTM.SubSide.XNEG_RT;
import static team.chisel.ctmlib.RenderBlocksCTM.SubSide.XPOS_LB;
import static team.chisel.ctmlib.RenderBlocksCTM.SubSide.XPOS_LT;
import static team.chisel.ctmlib.RenderBlocksCTM.SubSide.XPOS_RB;
import static team.chisel.ctmlib.RenderBlocksCTM.SubSide.XPOS_RT;
import static team.chisel.ctmlib.RenderBlocksCTM.SubSide.YNEG_LB;
import static team.chisel.ctmlib.RenderBlocksCTM.SubSide.YNEG_LT;
import static team.chisel.ctmlib.RenderBlocksCTM.SubSide.YNEG_RB;
import static team.chisel.ctmlib.RenderBlocksCTM.SubSide.YNEG_RT;
import static team.chisel.ctmlib.RenderBlocksCTM.SubSide.YPOS_LB;
import static team.chisel.ctmlib.RenderBlocksCTM.SubSide.YPOS_LT;
import static team.chisel.ctmlib.RenderBlocksCTM.SubSide.YPOS_RB;
import static team.chisel.ctmlib.RenderBlocksCTM.SubSide.YPOS_RT;
import static team.chisel.ctmlib.RenderBlocksCTM.SubSide.ZNEG_LB;
import static team.chisel.ctmlib.RenderBlocksCTM.SubSide.ZNEG_LT;
import static team.chisel.ctmlib.RenderBlocksCTM.SubSide.ZNEG_RB;
import static team.chisel.ctmlib.RenderBlocksCTM.SubSide.ZNEG_RT;
import static team.chisel.ctmlib.RenderBlocksCTM.SubSide.ZPOS_LB;
import static team.chisel.ctmlib.RenderBlocksCTM.SubSide.ZPOS_LT;
import static team.chisel.ctmlib.RenderBlocksCTM.SubSide.ZPOS_RB;
import static team.chisel.ctmlib.RenderBlocksCTM.SubSide.ZPOS_RT;
import static team.chisel.ctmlib.RenderBlocksCTM.Vert.X;
import static team.chisel.ctmlib.RenderBlocksCTM.Vert.XY;
import static team.chisel.ctmlib.RenderBlocksCTM.Vert.XYZ;
import static team.chisel.ctmlib.RenderBlocksCTM.Vert.XY_HALF;
import static team.chisel.ctmlib.RenderBlocksCTM.Vert.XY_HALF_Z;
import static team.chisel.ctmlib.RenderBlocksCTM.Vert.XZ;
import static team.chisel.ctmlib.RenderBlocksCTM.Vert.XZ_HALF;
import static team.chisel.ctmlib.RenderBlocksCTM.Vert.XZ_HALF_Y;
import static team.chisel.ctmlib.RenderBlocksCTM.Vert.X_HALF;
import static team.chisel.ctmlib.RenderBlocksCTM.Vert.X_HALF_Y;
import static team.chisel.ctmlib.RenderBlocksCTM.Vert.X_HALF_YZ;
import static team.chisel.ctmlib.RenderBlocksCTM.Vert.X_HALF_Z;
import static team.chisel.ctmlib.RenderBlocksCTM.Vert.Y;
import static team.chisel.ctmlib.RenderBlocksCTM.Vert.YZ;
import static team.chisel.ctmlib.RenderBlocksCTM.Vert.YZ_HALF;
import static team.chisel.ctmlib.RenderBlocksCTM.Vert.YZ_HALF_X;
import static team.chisel.ctmlib.RenderBlocksCTM.Vert.Y_HALF;
import static team.chisel.ctmlib.RenderBlocksCTM.Vert.Y_HALF_X;
import static team.chisel.ctmlib.RenderBlocksCTM.Vert.Y_HALF_XZ;
import static team.chisel.ctmlib.RenderBlocksCTM.Vert.Y_HALF_Z;
import static team.chisel.ctmlib.RenderBlocksCTM.Vert.Z;
import static team.chisel.ctmlib.RenderBlocksCTM.Vert.ZERO;
import static team.chisel.ctmlib.RenderBlocksCTM.Vert.Z_HALF;
import static team.chisel.ctmlib.RenderBlocksCTM.Vert.Z_HALF_X;
import static team.chisel.ctmlib.RenderBlocksCTM.Vert.Z_HALF_XY;
import static team.chisel.ctmlib.RenderBlocksCTM.Vert.Z_HALF_Y;
import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.util.IIcon;
import net.minecraftforge.common.util.ForgeDirection;
import lombok.Getter;
public class RenderBlocksCTM extends RenderBlocks {
/**
* An enum for all possible 26 sub-side vertices.
*
* The naming scheme is as follows:
*
* ZERO is a special case, it is the absolute min point of the block. X, Y, Z, or any combination means that the
* axes listed in the name are at 1. X, Y, Z, or any combination followed by HALF means that those axes are at 0.5.
* X, Y, Z, or any combination after a HALF means those axes are at 1.
*/
protected enum Vert {
// @formatter:off
ZERO(0, 0, 0),
XYZ(1, 1, 1),
X(1, 0, 0),
Y(0, 1, 0),
Z(0, 0, 1),
XY(1, 1, 0),
YZ(0, 1, 1),
XZ(1, 0, 1),
X_HALF(0.5, 0, 0),
Y_HALF(0, 0.5, 0),
Z_HALF(0, 0, 0.5),
XY_HALF(0.5, 0.5, 0),
YZ_HALF(0, 0.5, 0.5),
XZ_HALF(0.5, 0, 0.5),
X_HALF_Y(0.5, 1, 0),
X_HALF_Z(0.5, 0, 1),
Y_HALF_X(1, 0.5, 0),
Y_HALF_Z(0, 0.5, 1),
Z_HALF_X(1, 0, 0.5),
Z_HALF_Y(0, 1, 0.5),
X_HALF_YZ(0.5, 1, 1),
Y_HALF_XZ(1, 0.5, 1),
Z_HALF_XY(1, 1, 0.5),
XY_HALF_Z(0.5, 0.5, 1),
YZ_HALF_X(1, 0.5, 0.5),
XZ_HALF_Y(0.5, 1, 0.5);
// @formatter:on
private double x, y, z;
private Vert(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
private static double u, v, xDiff, yDiff, zDiff, uDiff, vDiff;
void render(RenderBlocksCTM inst, ForgeDirection normal, int cacheID) {
2024-02-19 11:43:31 -08:00
final Tessellator tessellator = Tessellator.instance;
2024-02-19 11:13:25 -08:00
if (inst.enableAO) {
2024-02-19 11:43:31 -08:00
tessellator.setColorOpaque_F(inst.redCache[cacheID], inst.grnCache[cacheID], inst.bluCache[cacheID]);
tessellator.setBrightness(inst.lightingCache[cacheID]);
2024-02-19 11:13:25 -08:00
}
u = cacheID == 1 || cacheID == 2 ? inst.maxU : inst.minU;
v = cacheID < 2 ? inst.maxV : inst.minV;
uDiff = inst.maxU - inst.minU;
vDiff = inst.maxV - inst.minV;
if (inst.renderMinX + inst.renderMinY + inst.renderMinZ != 0
|| inst.renderMaxX + inst.renderMaxY + inst.renderMaxZ != 3) {
boolean uMin = u == inst.minU;
boolean vMin = v == inst.minV;
xDiff = inst.renderMaxX - inst.renderMinX;
yDiff = inst.renderMaxY - inst.renderMinY;
zDiff = inst.renderMaxZ - inst.renderMinZ;
if (normal.offsetY != 0) {
uDiff *= uMin ? inst.renderMinX : 1 - inst.renderMaxX;
vDiff *= vMin ? inst.renderMinZ : 1 - inst.renderMaxZ;
} else if (normal.offsetX != 0) {
uDiff *= uMin ? inst.renderMinZ : 1 - inst.renderMaxZ;
vDiff *= vMin ? inst.renderMinY : 1 - inst.renderMaxY;
} else if (normal.offsetZ != 0) {
uDiff *= uMin ? inst.renderMinX : 1 - inst.renderMaxX;
vDiff *= vMin ? inst.renderMinY : 1 - inst.renderMaxY;
}
u = u == inst.minU ? inst.minU + uDiff : inst.maxU - uDiff;
v = v == inst.minV ? inst.minV + vDiff : inst.maxV - vDiff;
} else {
xDiff = yDiff = zDiff = 1;
}
2024-02-19 11:43:31 -08:00
tessellator.addVertexWithUV(
2024-02-19 11:13:25 -08:00
inst.renderMinX + (x * xDiff),
inst.renderMinY + (y * yDiff),
inst.renderMinZ + (z * zDiff),
u,
v);
}
}
/**
* Each side is divided into 4 sub-sides. LB(left bottom), RB(right bottom), LT(right top), and RT(right top).
*
* Each sub-side contains 4 {@link Vert} objects representing its position on the block.
*/
protected enum SubSide {
// @formatter:off
XNEG_LB(ZERO, Z_HALF, YZ_HALF, Y_HALF), XNEG_RB(Z_HALF, Z, Y_HALF_Z, YZ_HALF), XNEG_RT(YZ_HALF, Y_HALF_Z, YZ, Z_HALF_Y), XNEG_LT(Y_HALF, YZ_HALF, Z_HALF_Y, Y),
XPOS_LB(XZ, Z_HALF_X, YZ_HALF_X, Y_HALF_XZ), XPOS_RB(Z_HALF_X, X, Y_HALF_X, YZ_HALF_X), XPOS_RT(YZ_HALF_X, Y_HALF_X, XY, Z_HALF_XY), XPOS_LT(Y_HALF_XZ, YZ_HALF_X, Z_HALF_XY, XYZ),
ZNEG_LB(X, X_HALF, XY_HALF, Y_HALF_X), ZNEG_RB(X_HALF, ZERO, Y_HALF, XY_HALF), ZNEG_RT(XY_HALF, Y_HALF, Y, X_HALF_Y), ZNEG_LT(Y_HALF_X, XY_HALF, X_HALF_Y, XY),
ZPOS_LB(Z, X_HALF_Z, XY_HALF_Z, Y_HALF_Z), ZPOS_RB(X_HALF_Z, XZ, Y_HALF_XZ, XY_HALF_Z), ZPOS_RT(XY_HALF_Z, Y_HALF_XZ, XYZ, X_HALF_YZ), ZPOS_LT(Y_HALF_Z, XY_HALF_Z, X_HALF_YZ, YZ),
YNEG_LB(ZERO, X_HALF, XZ_HALF, Z_HALF), YNEG_RB(X_HALF, X, Z_HALF_X, XZ_HALF), YNEG_RT(XZ_HALF, Z_HALF_X, XZ, X_HALF_Z), YNEG_LT(Z_HALF, XZ_HALF, X_HALF_Z, Z),
YPOS_LB(YZ, X_HALF_YZ, XZ_HALF_Y, Z_HALF_Y), YPOS_RB(X_HALF_YZ, XYZ, Z_HALF_XY, XZ_HALF_Y), YPOS_RT(XZ_HALF_Y, Z_HALF_XY, XY, X_HALF_Y), YPOS_LT(Z_HALF_Y, XZ_HALF_Y, X_HALF_Y, Y);
// @formatter:on
private Vert xmin, xmax, ymin, ymax;
private ForgeDirection normal;
SubSide(Vert xmin, Vert ymin, Vert ymax, Vert xmax) {
this.xmin = xmin;
this.ymin = ymin;
this.ymax = ymax;
this.xmax = xmax;
this.normal = calcNormal();
}
private ForgeDirection calcNormal() {
double xTot = xmin.x + xmax.x + ymin.x + ymax.x;
double yTot = xmin.y + xmax.y + ymin.y + ymax.y;
double zTot = xmin.z + xmax.z + ymin.z + ymax.z;
if (xTot % 4 == 0) {
return xTot > 0 ? ForgeDirection.EAST : ForgeDirection.WEST;
} else if (yTot % 4 == 0) {
return yTot > 0 ? ForgeDirection.UP : ForgeDirection.DOWN;
} else if (zTot % 4 == 0) {
return zTot > 0 ? ForgeDirection.SOUTH : ForgeDirection.NORTH;
}
return ForgeDirection.UNKNOWN;
}
void render(RenderBlocksCTM inst) {
xmin.render(inst, normal, 0);
ymin.render(inst, normal, 1);
ymax.render(inst, normal, 2);
xmax.render(inst, normal, 3);
}
}
public CTM ctm = CTM.getInstance();
// globals added to save the JVM some trouble. No need to constantly create
// and destroy ints if we don't have to
protected int blockLightBitChannel = 0;
protected int redBitChannel = 0;
protected int greenBitChannel = 0;
protected int blueBitChannel = 0;
protected int sunlightBitChannel = 0;
public RenderBlocksCTM() {
super();
renderMaxX = renderMaxY = renderMaxZ = 1;
}
protected double minU, maxU;
protected double minV, maxV;
protected int[] lightingCache = new int[4];
protected float[] redCache = new float[4];
protected float[] grnCache = new float[4];
protected float[] bluCache = new float[4];
public TextureSubmap submap;
public TextureSubmap submapSmall;
public RenderBlocks rendererOld;
public ISubmapManager manager;
protected int[][] lightmap = new int[3][3];
protected float[][] redmap = new float[3][3];
protected float[][] grnmap = new float[3][3];
protected float[][] blumap = new float[3][3];
protected int bx, by, bz, meta;
@Getter
protected boolean inWorld = false;
@Override
public boolean renderStandardBlock(Block block, int x, int y, int z) {
bx = x;
by = y;
bz = z;
meta = Minecraft.getMinecraft().theWorld.getBlockMetadata(x, y, z);
2024-02-19 11:43:31 -08:00
final Tessellator tessellator = Tessellator.instance;
2024-02-19 11:13:25 -08:00
2024-02-19 11:43:31 -08:00
tessellator.setColorOpaque_F(1.0F, 1.0F, 1.0F);
tessellator.addTranslation(x, y, z);
2024-02-19 11:13:25 -08:00
if (rendererOld != null && rendererOld.hasOverrideBlockTexture()) {
setOverrideBlockTexture(rendererOld.overrideBlockTexture);
}
inWorld = true;
boolean res = super.renderStandardBlock(block, x, y, z);
inWorld = false;
2024-02-19 11:43:31 -08:00
tessellator.addTranslation(-x, -y, -z);
2024-02-19 11:13:25 -08:00
return res;
}
/* @formatter:off
* This method fills a 3x3 grid of light values based on the four corners, by averaging them together.
*
* 2 TL x TR
*
* 1 x x x
*
* 0 BL x BR
* 0 1 2
*
* Note: Variable names mean nothing... don't touch
*
* ._.
*
* shakes fist in anger
*/
// @formatter:on
protected void fillLightmap(int bottomLeft, int bottomRight, int topRight, int topLeft) {
lightmap[0][0] = bottomLeft;
lightmap[2][0] = bottomRight;
lightmap[2][2] = topRight;
lightmap[0][2] = topLeft;
lightmap[1][0] = avg(bottomLeft, bottomRight);
lightmap[2][1] = avg(bottomRight, topRight);
lightmap[1][2] = avg(topRight, topLeft);
lightmap[0][1] = avg(topLeft, bottomLeft);
lightmap[1][1] = avg(bottomLeft, bottomRight, topRight, topLeft);
}
protected void fillColormap(float bottomLeft, float bottomRight, float topRight, float topLeft, float[][] map) {
map[0][0] = bottomLeft;
map[2][0] = bottomRight;
map[2][2] = topRight;
map[0][2] = topLeft;
map[1][0] = (bottomLeft + bottomRight) / 2.0F;
map[2][1] = (bottomRight + topRight) / 2.0F;
map[1][2] = (topRight + topLeft) / 2.0F;
map[0][1] = (topLeft + bottomLeft) / 2.0F;
map[1][1] = (bottomLeft + bottomRight + topRight + topLeft) / 4.0F;
}
protected void getLight(int x, int y) {
lightingCache[0] = lightmap[0 + x][0 + y];
lightingCache[1] = lightmap[1 + x][0 + y];
lightingCache[2] = lightmap[1 + x][1 + y];
lightingCache[3] = lightmap[0 + x][1 + y];
redCache[0] = redmap[0 + x][0 + y];
redCache[1] = redmap[1 + x][0 + y];
redCache[2] = redmap[1 + x][1 + y];
redCache[3] = redmap[0 + x][1 + y];
grnCache[0] = grnmap[0 + x][0 + y];
grnCache[1] = grnmap[1 + x][0 + y];
grnCache[2] = grnmap[1 + x][1 + y];
grnCache[3] = grnmap[0 + x][1 + y];
bluCache[0] = blumap[0 + x][0 + y];
bluCache[1] = blumap[1 + x][0 + y];
bluCache[2] = blumap[1 + x][1 + y];
bluCache[3] = blumap[0 + x][1 + y];
}
/**
* This works around a bug in CLC atm
*/
private int avg(int... lightVals) {
blockLightBitChannel = 0;
redBitChannel = 0;
greenBitChannel = 0;
blueBitChannel = 0;
sunlightBitChannel = 0;
for (int light : lightVals) {
blockLightBitChannel += (light & 0xFF);
redBitChannel += (light & 0xF00);
greenBitChannel += (light & 0xF000);
blueBitChannel += (light & 0xF0000);
sunlightBitChannel += (light & 0xF00000);
}
return ((blockLightBitChannel / lightVals.length) & 0xFF) | ((redBitChannel / lightVals.length) & 0xF00)
| ((greenBitChannel / lightVals.length) & 0xF000)
| ((blueBitChannel / lightVals.length) & 0xF0000)
| ((sunlightBitChannel / lightVals.length) & 0xF00000);
}
protected void side(Block block, SubSide side, int iconIndex) {
2025-12-30 02:37:43 +03:00
// If we have an overridden texture when we're supposed to render a CTM texture,
// we'll treat it as a normal block texture but still render it the CTM way: quarter of a texture at a time.
// This way has one benefit: if an overridden texture is a base block texture and a CTM texture (that is being
// rendered next) is an overlay texture above the base, we're avoiding any z-fighting issues because we
// create identical vertices and now only order of rendering dictates which texture will be rendered above
if (hasOverrideBlockTexture()) {
IIcon icon = overrideBlockTexture;
double u0 = icon.getMinU();
double u1 = icon.getMaxU();
double v0 = icon.getMinV();
double v1 = icon.getMaxV();
double uMid = (u0 + u1) / 2;
double vMid = (v0 + v1) / 2;
// Map all LB-style subsides to bottom-left quarter, RB to bottom-right, RT to top-right, LT to top-left
switch (side) {
// bottom-left quarter
case XNEG_LB, XPOS_LB, YNEG_LB, YPOS_LB, ZNEG_LB, ZPOS_LB -> {
minU = u0;
maxU = uMid;
minV = vMid;
maxV = v1;
}
// bottom-right quarter
case XNEG_RB, XPOS_RB, YNEG_RB, YPOS_RB, ZNEG_RB, ZPOS_RB -> {
minU = uMid;
maxU = u1;
minV = vMid;
maxV = v1;
}
// top-right quarter
case XNEG_RT, XPOS_RT, YNEG_RT, YPOS_RT, ZNEG_RT, ZPOS_RT -> {
minU = uMid;
maxU = u1;
minV = v0;
maxV = vMid;
}
// top-left quarter
case XNEG_LT, XPOS_LT, YNEG_LT, YPOS_LT, ZNEG_LT, ZPOS_LT -> {
minU = u0;
maxU = uMid;
minV = v0;
maxV = vMid;
}
}
side.render(this);
return;
}
2024-02-19 11:13:25 -08:00
IIcon icon;
TextureSubmap map;
if (iconIndex >= 16) {
iconIndex -= 16;
map = submapSmall;
} else {
map = submap;
}
if (map == null) {
icon = getBlockIconFromSideAndMetadata(block, side.normal.ordinal(), meta);
} else {
int x = iconIndex % map.getWidth();
int y = iconIndex / map.getHeight();
icon = map.getSubIcon(x, y);
}
2025-12-30 02:37:43 +03:00
minU = icon.getMinU();
maxU = icon.getMaxU();
minV = icon.getMinV();
maxV = icon.getMaxV();
2024-02-19 11:13:25 -08:00
side.render(this);
}
@Override
public void renderFaceXNeg(Block block, double x, double y, double z, IIcon icon) {
pre(ForgeDirection.WEST);
2025-12-30 02:37:43 +03:00
if (!inWorld || submap == null) {
2024-02-19 11:13:25 -08:00
super.renderFaceXNeg(block, 0, 0, 0, icon);
} else {
int tex[] = ctm.getSubmapIndices(blockAccess, bx, by, bz, 4);
fillLightmap(brightnessBottomRight, brightnessTopRight, brightnessTopLeft, brightnessBottomLeft);
fillColormap(colorRedBottomRight, colorRedTopRight, colorRedTopLeft, colorRedBottomLeft, redmap);
fillColormap(colorGreenBottomRight, colorGreenTopRight, colorGreenTopLeft, colorGreenBottomLeft, grnmap);
fillColormap(colorBlueBottomRight, colorBlueTopRight, colorBlueTopLeft, colorBlueBottomLeft, blumap);
getLight(0, 0);
side(block, XNEG_LB, tex[0]);
getLight(1, 0);
side(block, XNEG_RB, tex[1]);
getLight(1, 1);
side(block, XNEG_RT, tex[2]);
getLight(0, 1);
side(block, XNEG_LT, tex[3]);
}
post(ForgeDirection.WEST);
}
@Override
public void renderFaceXPos(Block block, double x, double y, double z, IIcon icon) {
pre(ForgeDirection.EAST);
2025-12-30 02:37:43 +03:00
if (!inWorld || submap == null) {
2024-02-19 11:13:25 -08:00
super.renderFaceXPos(block, 0, 0, 0, icon);
} else {
int tex[] = ctm.getSubmapIndices(blockAccess, bx, by, bz, 5);
fillLightmap(brightnessTopLeft, brightnessBottomLeft, brightnessBottomRight, brightnessTopRight);
fillColormap(colorRedTopLeft, colorRedBottomLeft, colorRedBottomRight, colorRedTopRight, redmap);
fillColormap(colorGreenTopLeft, colorGreenBottomLeft, colorGreenBottomRight, colorGreenTopRight, grnmap);
fillColormap(colorBlueTopLeft, colorBlueBottomLeft, colorBlueBottomRight, colorBlueTopRight, blumap);
getLight(0, 0);
side(block, XPOS_LB, tex[0]);
getLight(1, 0);
side(block, XPOS_RB, tex[1]);
getLight(1, 1);
side(block, XPOS_RT, tex[2]);
getLight(0, 1);
side(block, XPOS_LT, tex[3]);
}
post(ForgeDirection.EAST);
}
@Override
public void renderFaceZNeg(Block block, double x, double y, double z, IIcon icon) {
pre(ForgeDirection.NORTH);
2025-12-30 02:37:43 +03:00
if (!inWorld || submap == null) {
2024-02-19 11:13:25 -08:00
super.renderFaceZNeg(block, 0, 0, 0, icon);
} else {
int tex[] = ctm.getSubmapIndices(blockAccess, bx, by, bz, 2);
fillLightmap(brightnessBottomRight, brightnessTopRight, brightnessTopLeft, brightnessBottomLeft);
fillColormap(colorRedBottomRight, colorRedTopRight, colorRedTopLeft, colorRedBottomLeft, redmap);
fillColormap(colorGreenBottomRight, colorGreenTopRight, colorGreenTopLeft, colorGreenBottomLeft, grnmap);
fillColormap(colorBlueBottomRight, colorBlueTopRight, colorBlueTopLeft, colorBlueBottomLeft, blumap);
getLight(0, 0);
side(block, ZNEG_LB, tex[0]);
getLight(1, 0);
side(block, ZNEG_RB, tex[1]);
getLight(1, 1);
side(block, ZNEG_RT, tex[2]);
getLight(0, 1);
side(block, ZNEG_LT, tex[3]);
}
post(ForgeDirection.NORTH);
}
@Override
public void renderFaceZPos(Block block, double x, double y, double z, IIcon icon) {
pre(ForgeDirection.SOUTH);
2025-12-30 02:37:43 +03:00
if (!inWorld || submap == null) {
2024-02-19 11:13:25 -08:00
super.renderFaceZPos(block, 0, 0, 0, icon);
} else {
int tex[] = ctm.getSubmapIndices(blockAccess, bx, by, bz, 3);
fillLightmap(brightnessBottomLeft, brightnessBottomRight, brightnessTopRight, brightnessTopLeft);
fillColormap(colorRedBottomLeft, colorRedBottomRight, colorRedTopRight, colorRedTopLeft, redmap);
fillColormap(colorGreenBottomLeft, colorGreenBottomRight, colorGreenTopRight, colorGreenTopLeft, grnmap);
fillColormap(colorBlueBottomLeft, colorBlueBottomRight, colorBlueTopRight, colorBlueTopLeft, blumap);
getLight(0, 0);
side(block, ZPOS_LB, tex[0]);
getLight(1, 0);
side(block, ZPOS_RB, tex[1]);
getLight(1, 1);
side(block, ZPOS_RT, tex[2]);
getLight(0, 1);
side(block, ZPOS_LT, tex[3]);
}
post(ForgeDirection.SOUTH);
}
@Override
public void renderFaceYNeg(Block block, double x, double y, double z, IIcon icon) {
pre(ForgeDirection.DOWN);
2025-12-30 02:37:43 +03:00
if (!inWorld || submap == null) {
2024-02-19 11:13:25 -08:00
super.renderFaceYNeg(block, 0, 0, 0, icon);
} else {
int tex[] = ctm.getSubmapIndices(blockAccess, bx, by, bz, 0);
fillLightmap(brightnessBottomLeft, brightnessBottomRight, brightnessTopRight, brightnessTopLeft);
fillColormap(colorRedBottomLeft, colorRedBottomRight, colorRedTopRight, colorRedTopLeft, redmap);
fillColormap(colorGreenBottomLeft, colorGreenBottomRight, colorGreenTopRight, colorGreenTopLeft, grnmap);
fillColormap(colorBlueBottomLeft, colorBlueBottomRight, colorBlueTopRight, colorBlueTopLeft, blumap);
getLight(0, 0);
side(block, YNEG_LB, tex[0]);
getLight(1, 0);
side(block, YNEG_RB, tex[1]);
getLight(1, 1);
side(block, YNEG_RT, tex[2]);
getLight(0, 1);
side(block, YNEG_LT, tex[3]);
}
post(ForgeDirection.DOWN);
}
@Override
public void renderFaceYPos(Block block, double x, double y, double z, IIcon icon) {
pre(ForgeDirection.UP);
2025-12-30 02:37:43 +03:00
if (!inWorld || submap == null) {
2024-02-19 11:13:25 -08:00
super.renderFaceYPos(block, 0, 0, 0, icon);
} else {
int tex[] = ctm.getSubmapIndices(blockAccess, bx, by, bz, 1);
fillLightmap(brightnessTopRight, brightnessTopLeft, brightnessBottomLeft, brightnessBottomRight);
fillColormap(colorRedTopRight, colorRedTopLeft, colorRedBottomLeft, colorRedBottomRight, redmap);
fillColormap(colorGreenTopRight, colorGreenTopLeft, colorGreenBottomLeft, colorGreenBottomRight, grnmap);
fillColormap(colorBlueTopRight, colorBlueTopLeft, colorBlueBottomLeft, colorBlueBottomRight, blumap);
getLight(0, 0);
side(block, YPOS_LB, tex[0]);
getLight(1, 0);
side(block, YPOS_RB, tex[1]);
getLight(1, 1);
side(block, YPOS_RT, tex[2]);
getLight(0, 1);
side(block, YPOS_LT, tex[3]);
}
post(ForgeDirection.UP);
}
protected void pre(ForgeDirection face) {
manager.preRenderSide(this, blockAccess, bx, by, bz, face);
}
protected void post(ForgeDirection face) {
manager.postRenderSide(this, blockAccess, bx, by, bz, face);
}
}