package shedar.mods.ic2.nuclearcontrol.renderers.model;
import net.minecraft.block.Block;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.util.IIcon;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.opengl.GL11;
import shedar.mods.ic2.nuclearcontrol.panel.Screen;
import shedar.mods.ic2.nuclearcontrol.tileentities.TileEntityAdvancedInfoPanel;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
public class ModelInfoPanel {
private static final String TEXTURE_FILE = "nuclearcontrol:textures/blocks/infoPanel/panelAdvancedSide.png";
private static final ResourceLocation TEXTURE_LOCATION = new ResourceLocation(TEXTURE_FILE);
private double[] coordinates = new double[24];
private void assignWithRotation(int rotation, int offset, int sign, int tl,
int tr, int br, int bl, double dtl, double dtr, double dbr,
double dbl) {
switch (rotation) {
case 0:
coordinates[tl * 3 + offset] += sign * dtl;
coordinates[tr * 3 + offset] += sign * dtr;
coordinates[br * 3 + offset] += sign * dbr;
coordinates[bl * 3 + offset] += sign * dbl;
break;
case 1:
coordinates[tl * 3 + offset] += sign * dbl;
coordinates[tr * 3 + offset] += sign * dtl;
coordinates[br * 3 + offset] += sign * dtr;
coordinates[bl * 3 + offset] += sign * dbr;
break;
case 2:
coordinates[tl * 3 + offset] += sign * dtr;
coordinates[tr * 3 + offset] += sign * dbr;
coordinates[br * 3 + offset] += sign * dbl;
coordinates[bl * 3 + offset] += sign * dtl;
break;
case 3:
coordinates[tl * 3 + offset] += sign * dbr;
coordinates[tr * 3 + offset] += sign * dbl;
coordinates[br * 3 + offset] += sign * dtl;
coordinates[bl * 3 + offset] += sign * dtr;
break;
default:
break;
}
}
public double[] getDeltas(TileEntityAdvancedInfoPanel panel, Screen screen) {
boolean isTopBottom = panel.rotateVert != 0;
boolean isLeftRight = panel.rotateHor != 0;
double dTopLeft = 0;
double dTopRight = 0;
double dBottomLeft = 0;
double dBottomRight = 0;
int height = screen.getHeight(panel);
int width = screen.getWidth(panel);
double maxDelta = 0;
if (isTopBottom) {
if (panel.rotateVert > 0) // |\
{ // | \
dBottomRight = dBottomLeft = height
* Math.tan(Math.PI * panel.rotateVert / 180);
maxDelta = dBottomLeft;
} else {
dTopRight = dTopLeft = height
* Math.tan(Math.PI * -panel.rotateVert / 180);
maxDelta = dTopRight;
}
}
if (isLeftRight) {
if (panel.rotateHor > 0) // -------
{ // | . '
dTopRight = dBottomRight = width
* Math.tan(Math.PI * panel.rotateHor / 180);
maxDelta = dTopRight;
} else {
dTopLeft = dBottomLeft = width
* Math.tan(Math.PI * -panel.rotateHor / 180);
maxDelta = dBottomLeft;
}
}
if (isTopBottom && isLeftRight) {
if (dTopLeft == 0) {
maxDelta = dBottomRight = dBottomLeft + dTopRight;
} else if (dTopRight == 0) {
maxDelta = dBottomLeft = dTopLeft + dBottomRight;
} else if (dBottomLeft == 0) {
maxDelta = dTopRight = dTopLeft + dBottomRight;
} else {
maxDelta = dTopLeft = dBottomLeft + dTopRight;
}
}
double thickness = panel.thickness / 16D;
if (maxDelta > thickness) {
double scale = thickness / maxDelta;
dTopLeft = scale * dTopLeft;
dTopRight = scale * dTopRight;
dBottomLeft = scale * dBottomLeft;
dBottomRight = scale * dBottomRight;
}
double[] res = { dTopLeft, dTopRight, dBottomLeft, dBottomRight };
return res;
}
private void addSlopes(TileEntityAdvancedInfoPanel panel, Screen screen,
double[] deltas) {
// if (panel.rotateVert == 0 && panel.rotateHor == 0)
// return;
double dTopLeft = deltas[0];
double dTopRight = deltas[1];
double dBottomLeft = deltas[2];
double dBottomRight = deltas[3];
int facing = panel.facing;
int rotation = panel.getRotation();
switch (facing) {
case 0:
assignWithRotation(rotation, 1, -1, 4, 7, 6, 5, dTopLeft,
dTopRight, dBottomRight, dBottomLeft);
break;
case 1:
assignWithRotation(rotation, 1, 1, 3, 0, 1, 2, dTopLeft, dTopRight,
dBottomRight, dBottomLeft);
break;
case 2:
assignWithRotation(rotation, 2, -1, 5, 6, 2, 1, dTopLeft,
dTopRight, dBottomRight, dBottomLeft);
break;
case 3:
assignWithRotation(rotation, 2, 1, 7, 4, 0, 3, dTopLeft, dTopRight,
dBottomRight, dBottomLeft);
break;
case 4:
assignWithRotation(rotation, 0, -1, 6, 7, 3, 2, dTopLeft,
dTopRight, dBottomRight, dBottomLeft);
break;
case 5:
assignWithRotation(rotation, 0, 1, 4, 5, 1, 0, dTopLeft, dTopRight,
dBottomRight, dBottomLeft);
break;
}
}
private void initCoordinates(Block block, Screen screen) {
// 5o ----- o6
// 4o ----- o7
// / | /
// / 1o / o2
// 0o ----- o3
double blockMinX = block.getBlockBoundsMinX();
double blockMinY = block.getBlockBoundsMinY();
double blockMinZ = block.getBlockBoundsMinZ();
double blockMaxX = block.getBlockBoundsMaxX();
double blockMaxY = block.getBlockBoundsMaxY();
double blockMaxZ = block.getBlockBoundsMaxZ();
/* 0 */
coordinates[0] = screen.minX + blockMinX;
coordinates[1] = screen.minY + blockMinY;
coordinates[2] = screen.minZ + blockMinZ;
/* 1 */
coordinates[3] = screen.minX + blockMinX;
coordinates[4] = screen.minY + blockMinY;
coordinates[5] = screen.maxZ + blockMaxZ;
/* 2 */
coordinates[6] = screen.maxX + blockMaxX;
coordinates[7] = screen.minY + blockMinY;
coordinates[8] = screen.maxZ + blockMaxZ;
/* 3 */
coordinates[9] = screen.maxX + blockMaxX;
coordinates[10] = screen.minY + blockMinY;
coordinates[11] = screen.minZ + blockMinZ;
/* 4 */
coordinates[12] = screen.minX + blockMinX;
coordinates[13] = screen.maxY + blockMaxY;
coordinates[14] = screen.minZ + blockMinZ;
/* 5 */
coordinates[15] = screen.minX + blockMinX;
coordinates[16] = screen.maxY + blockMaxY;
coordinates[17] = screen.maxZ + blockMaxZ;
/* 6 */
coordinates[18] = screen.maxX + blockMaxX;
coordinates[19] = screen.maxY + blockMaxY;
coordinates[20] = screen.maxZ + blockMaxZ;
/* 7 */
coordinates[21] = screen.maxX + blockMaxX;
coordinates[22] = screen.maxY + blockMaxY;
coordinates[23] = screen.minZ + blockMinZ;
}
private void addPoint(int point, double u, double v) {
Tessellator.instance.addVertexWithUV(coordinates[point * 3],
coordinates[point * 3 + 1], coordinates[point * 3 + 2], u, v);
}
private void drawFacing(int facing, int rotation, Screen screen, TileEntityAdvancedInfoPanel panel, Block block, Tessellator tess) {
// TODO: refactor here
int point = 0;
int pointR = 0;
int pointB = 0;
int pointRB = 0;
int offsetH = 0;
int offsetV = 0;
int offsetD = 0;
boolean ccw = false;
switch (facing) {
case 0:
tess.setNormal(0, -1, 0);
point = 3;
pointR = 0;
pointB = 2;
pointRB = 1;
offsetH = 0;
offsetV = 2;
offsetD = 1;
ccw = true;
break;
case 1:
tess.setNormal(0, 1, 0);
point = 4;
pointR = 7;
pointB = 5;
pointRB = 6;
offsetH = 0;
offsetV = 2;
offsetD = 1;
break;
case 2:
tess.setNormal(0, 0, -1);
point = 7;
pointR = 4;
pointB = 3;
pointRB = 0;
offsetH = 0;
offsetV = 1;
offsetD = 2;
ccw = rotation == 1 || rotation == 2;
break;
case 3:
tess.setNormal(0, 0, 1);
point = 5;
pointR = 6;
pointB = 1;
pointRB = 2;
offsetH = 0;
offsetV = 1;
offsetD = 2;
break;
case 4:
tess.setNormal(-1, 0, 0);
point = 4;
pointR = 5;
pointB = 0;
pointRB = 1;
offsetH = 2;
offsetV = 1;
offsetD = 0;
break;
case 5:
tess.setNormal(1, 0, 0);
point = 6;
pointR = 7;
pointB = 2;
pointRB = 3;
offsetH = 2;
offsetV = 1;
offsetD = 0;
ccw = rotation == 1 || rotation == 2;
break;
}
switch (rotation) {
case 1:
int tmp = offsetH;
offsetH = offsetV;
offsetV = tmp;
pointB = point;
point = pointR;
pointR = pointRB;
break;
case 2:
tmp = offsetH;
offsetH = offsetV;
offsetV = tmp;
pointR = point;
point = pointB;
pointB = pointRB;
break;
case 3:
point = pointRB;
tmp = pointR;
pointR = pointB;
pointB = tmp;
break;
}
int stepsHor = screen.getWidth(panel);
int stepsVert = screen.getHeight(panel);
int sh = 0;
double dh = (coordinates[pointR * 3 + offsetH] - coordinates[point * 3
+ offsetH])
/ stepsHor;
double dv = (coordinates[pointB * 3 + offsetV] - coordinates[point * 3
+ offsetV])
/ stepsVert;
double ddh = (coordinates[pointR * 3 + offsetD] - coordinates[point * 3
+ offsetD])
/ stepsHor;
double ddv = (coordinates[pointB * 3 + offsetD] - coordinates[point * 3
+ offsetD])
/ stepsVert;
double[] base = new double[] { coordinates[point * 3],
coordinates[point * 3 + 1], coordinates[point * 3 + 2] };
double[] midpoint = new double[3];
while (sh < stepsHor) {
int sv = 0;
while (sv < stepsVert) {
double[] p = base.clone();
p[offsetH] += dh * sh;
p[offsetV] += dv * sv;
p[offsetD] += ddh * sh + ddv * sv;
midpoint[offsetH] = p[offsetH] + dh / 2;
midpoint[offsetV] = p[offsetV] + dv / 2;
midpoint[offsetD] = p[offsetD] + (ddh + ddv) / 2;
IIcon texture = block.getIcon(panel.getWorldObj(),
(int) Math.floor(midpoint[0]),
(int) Math.floor(midpoint[1]),
(int) Math.floor(midpoint[2]), facing);
double u1 = texture.getMinU();
double u2 = texture.getMaxU();
double v1 = texture.getMinV();
double v2 = texture.getMaxV();
if (ccw) {
double tu = u1;
u1 = u2;
u2 = tu;
}
tess.addVertexWithUV(p[0], p[1], p[2], u1, v1);
p[offsetV] += dv;
p[offsetD] += ddv;
tess.addVertexWithUV(p[0], p[1], p[2], u1, v2);
p[offsetH] += dh;
p[offsetD] += ddh;
tess.addVertexWithUV(p[0], p[1], p[2], u2, v2);
p[offsetV] -= dv;
p[offsetD] -= ddv;
tess.addVertexWithUV(p[0], p[1], p[2], u2, v1);
sv++;
}
sh++;
}
}
public void renderScreen(Block block, TileEntityAdvancedInfoPanel panel, double x, double y, double z, RenderBlocks renderer) {
Screen screen = panel.getScreen();
if (screen == null)
return;
initCoordinates(block, screen);
double[] deltas = getDeltas(panel, screen);
addSlopes(panel, screen, deltas);
int facing = panel.getFacing();
Tessellator tess = Tessellator.instance;
tess.setBrightness(block.getMixedBrightnessForBlock(panel.getWorldObj(), panel.xCoord, panel.yCoord, panel.zCoord));
tess.setColorOpaque_F(0.5F, 0.5F, 0.5F);
drawFacing(facing, panel.getRotation(), screen, panel, block, tess);
//
tess.draw();
//SIDES
Tessellator.instance.startDrawingQuads();
renderer.minecraftRB.renderEngine.bindTexture(TEXTURE_LOCATION);
Tessellator.instance.setBrightness(block.getMixedBrightnessForBlock(panel.getWorldObj(), panel.xCoord, panel.yCoord, panel.zCoord));
Tessellator.instance.setColorOpaque_F(0.5F, 0.5F, 0.5F);
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
int dx = screen.getDx() + 1;
int dy = screen.getDy() + 1;
int dz = screen.getDz() + 1;
// bottom
if (facing != 0) {
Tessellator.instance.setNormal(0, -1, 0);
addPoint(0, 0, 0);
addPoint(3, dx, 0);
addPoint(2, dx, dz);
addPoint(1, 0, dz);
}
if (facing != 1) {
Tessellator.instance.setNormal(0, 1, 0);
addPoint(4, 0, 0);
addPoint(5, dz, 0);
addPoint(6, dz, dx);
addPoint(7, 0, dx);
}
if (facing != 2) {
Tessellator.instance.setNormal(0, 0, -1);
addPoint(0, 0, 0);
addPoint(4, dy, 0);
addPoint(7, dy, dx);
addPoint(3, 0, dx);
}
if (facing != 3) {
Tessellator.instance.setNormal(0, 0, 1);
addPoint(6, 0, 0);
addPoint(5, dx, 0);
addPoint(1, dx, dy);
addPoint(2, 0, dy);
}
if (facing != 4) {
Tessellator.instance.setNormal(-1, 0, 0);
addPoint(5, 0, 0);
addPoint(4, dz, 0);
addPoint(0, dz, dy);
addPoint(1, 0, dy);
}
if (facing != 5) {
Tessellator.instance.setNormal(1, 0, 0);
addPoint(2, 0, 0);
addPoint(3, dz, 0);
addPoint(7, dz, dy);
addPoint(6, 0, dy);
}
Tessellator.instance.draw();
//RETURN TO MC DRAWING
Tessellator.instance.startDrawingQuads();
renderer.minecraftRB.renderEngine.bindTexture(TEXTURE_LOCATION);
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
Tessellator.instance.setColorOpaque_F(0.5F, 0.5F, 0.5F);
renderer.minecraftRB.renderEngine.bindTexture(TextureMap.locationBlocksTexture/* blocks texture atlas*/);
}
}