blob: 570523a204f478b84fa573902d4033be66bb38eb [file] [log] [blame] [raw]
package li.cil.oc.client.renderer.tileentity
import li.cil.oc.Settings
import li.cil.oc.common.tileentity.Cable
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
import net.minecraft.client.renderer.{Tessellator, GLAllocation}
import net.minecraft.tileentity.TileEntity
import net.minecraft.util.ResourceLocation
import net.minecraftforge.common.ForgeDirection
import org.lwjgl.opengl.GL11
object CableRenderer extends TileEntitySpecialRenderer {
private val texture = new ResourceLocation(Settings.resourceDomain, "textures/blocks/cable.png")
private val displayLists = GLAllocation.generateDisplayLists(64)
def compileLists() {
val t = Tessellator.instance
val lb = 0.375
val ub = 0.625
val s = 0.25
val t1 = Array(ub, ub, lb, lb)
val t2 = Array(lb, ub, ub, lb)
val uv1 = Array(0, 0, 0.5, 0.5)
val uv2 = Array(0.5, 0, 0, 0.5)
val uo = 4.0 / 8.0
val vs = 6.0 / 4.0
val translations = Array(Array(lb, 0, 0), Array(0, lb, 0), Array(0, 0, lb))
val offsets = Array(Array(s, 0, 0), Array(0, s, 0), Array(0, 0, s))
val normals = Array(
Array(ForgeDirection.EAST, ForgeDirection.WEST, ForgeDirection.SOUTH, ForgeDirection.NORTH),
Array(ForgeDirection.NORTH, ForgeDirection.SOUTH, ForgeDirection.WEST, ForgeDirection.EAST),
Array(ForgeDirection.UP, ForgeDirection.DOWN, ForgeDirection.WEST, ForgeDirection.EAST),
Array(ForgeDirection.WEST, ForgeDirection.EAST, ForgeDirection.DOWN, ForgeDirection.UP),
Array(ForgeDirection.SOUTH, ForgeDirection.NORTH, ForgeDirection.DOWN, ForgeDirection.UP),
Array(ForgeDirection.UP, ForgeDirection.DOWN, ForgeDirection.NORTH, ForgeDirection.SOUTH)
)
def normal(side: ForgeDirection, n: Int) {
val v = normals(side.ordinal())(n)
t.setNormal(v.offsetX, v.offsetY, v.offsetZ)
}
def uv(i: Int) = (i + 4) % 4
for (mask <- 0 to 0xFF >> 2) {
GL11.glNewList(displayLists + mask, GL11.GL_COMPILE)
for (side <- ForgeDirection.VALID_DIRECTIONS) {
val connects = (side.flag & mask) != 0
val z = if (connects) 0 else lb
val uc = if (ForgeDirection.VALID_DIRECTIONS.
filter(_ != side).filter(_ != side.getOpposite).
exists(s => (s.flag & mask) != 0)) uo
else 0
t.startDrawingQuads()
t.setNormal(side.offsetX, side.offsetY, -side.offsetZ)
val (tx, ty, tz, u, v) = side match {
case ForgeDirection.WEST => (Array.fill(4)(z), t2, t1, uv1.reverse, uv2)
case ForgeDirection.EAST => (Array.fill(4)(1 - z), t1, t2, uv2, uv1)
case ForgeDirection.DOWN => (t1, Array.fill(4)(z), t2, uv1.reverse, uv2)
case ForgeDirection.UP => (t2, Array.fill(4)(1 - z), t1, uv2, uv1)
case ForgeDirection.NORTH => (t2, t1, Array.fill(4)(z), uv2, uv1)
case ForgeDirection.SOUTH => (t1, t2, Array.fill(4)(1 - z), uv1.reverse, uv2)
case _ => throw new AssertionError()
}
t.addVertexWithUV(tx(0), ty(0), tz(0), u(0) + uc, v(0))
t.addVertexWithUV(tx(1), ty(1), tz(1), u(1) + uc, v(1))
t.addVertexWithUV(tx(2), ty(2), tz(2), u(2) + uc, v(2))
t.addVertexWithUV(tx(3), ty(3), tz(3), u(3) + uc, v(3))
t.draw()
if (connects) {
val (axis, sign, uv1, uv2, uv3, uv4) = side match {
case ForgeDirection.WEST => (0, -1, 1, 1, 1, 1)
case ForgeDirection.EAST => (0, 1, 3, 3, 1, 1)
case ForgeDirection.DOWN => (1, -1, 1, 3, 2, 0)
case ForgeDirection.UP => (1, 1, 2, 0, 3, 1)
case ForgeDirection.NORTH => (2, -1, 0, 2, 1, 1)
case ForgeDirection.SOUTH => (2, 1, 1, 1, 0, 2)
case _ => throw new AssertionError()
}
val tl = translations(axis)
val o1 = offsets((axis + sign + 3) % 3)
val o2 = offsets((axis - sign + 3) % 3)
t.startDrawingQuads()
normal(side, 0)
t.addVertexWithUV(tx(0) - sign * tl(0), ty(0) - sign * tl(1), tz(0) - sign * tl(2), u(uv(0 + uv1)) + uo, v(uv(0 + uv1)) * vs)
t.addVertexWithUV(tx(1) - sign * tl(0), ty(1) - sign * tl(1), tz(1) - sign * tl(2), u(uv(1 + uv1)) + uo, v(uv(1 + uv1)) * vs)
t.addVertexWithUV(tx(2) + o1(0), ty(2) + o1(1), tz(2) + o1(2), u(uv(2 + uv1)) + uo, v(uv(2 + uv1)) * vs)
t.addVertexWithUV(tx(3) + o1(0), ty(3) + o1(1), tz(3) + o1(2), u(uv(3 + uv1)) + uo, v(uv(3 + uv1)) * vs)
t.draw()
t.startDrawingQuads()
normal(side, 1)
t.addVertexWithUV(tx(0) - o1(0), ty(0) - o1(1), tz(0) - o1(2), u(uv(0 + uv2)) + uo, v(uv(0 + uv2)) * vs)
t.addVertexWithUV(tx(1) - o1(0), ty(1) - o1(1), tz(1) - o1(2), u(uv(1 + uv2)) + uo, v(uv(1 + uv2)) * vs)
t.addVertexWithUV(tx(2) - sign * tl(0), ty(2) - sign * tl(1), tz(2) - sign * tl(2), u(uv(2 + uv2)) + uo, v(uv(2 + uv2)) * vs)
t.addVertexWithUV(tx(3) - sign * tl(0), ty(3) - sign * tl(1), tz(3) - sign * tl(2), u(uv(3 + uv2)) + uo, v(uv(3 + uv2)) * vs)
t.draw()
t.startDrawingQuads()
normal(side, 2)
t.addVertexWithUV(tx(0) - sign * tl(0), ty(0) - sign * tl(1), tz(0) - sign * tl(2), u(uv(0 + uv3)) + uo, v(uv(0 + uv3)) * vs)
t.addVertexWithUV(tx(1) - o2(0), ty(1) - o2(1), tz(1) - o2(2), u(uv(1 + uv3)) + uo, v(uv(1 + uv3)) * vs)
t.addVertexWithUV(tx(2) - o2(0), ty(2) - o2(1), tz(2) - o2(2), u(uv(2 + uv3)) + uo, v(uv(2 + uv3)) * vs)
t.addVertexWithUV(tx(3) - sign * tl(0), ty(3) - sign * tl(1), tz(3) - sign * tl(2), u(uv(3 + uv3)) + uo, v(uv(3 + uv3)) * vs)
t.draw()
t.startDrawingQuads()
normal(side, 3)
t.addVertexWithUV(tx(0) + o2(0), ty(0) + o2(1), tz(0) + o2(2), u(uv(0 + uv4)) + uo, v(uv(0 + uv4)) * vs)
t.addVertexWithUV(tx(1) - sign * tl(0), ty(1) - sign * tl(1), tz(1) - sign * tl(2), u(uv(1 + uv4)) + uo, v(uv(1 + uv4)) * vs)
t.addVertexWithUV(tx(2) - sign * tl(0), ty(2) - sign * tl(1), tz(2) - sign * tl(2), u(uv(2 + uv4)) + uo, v(uv(2 + uv4)) * vs)
t.addVertexWithUV(tx(3) + o2(0), ty(3) + o2(1), tz(3) + o2(2), u(uv(3 + uv4)) + uo, v(uv(3 + uv4)) * vs)
t.draw()
}
}
GL11.glEndList()
}
}
compileLists()
def renderCable(neighbors: Int) {
bindTexture(texture)
GL11.glCallList(displayLists + neighbors)
}
def renderTileEntityAt(t: TileEntity, x: Double, y: Double, z: Double, f: Float) {
val cable = t.asInstanceOf[Cable]
GL11.glTranslated(x, y, z)
renderCable(cable.neighbors)
GL11.glTranslated(-x, -y, -z)
}
}