From 22a6a3d402e61aec1eb497a10d537941320e3d56 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 4 Dec 2016 18:02:25 -0500 Subject: [PATCH] model viewer: load normals and enable cull face --- .../cache/definitions/ModelDefinition.java | 101 ++++++++++++++++++ .../definitions/loaders/ModelLoader.java | 2 + .../net/runelite/cache/models/FaceNormal.java | 8 ++ .../net/runelite/cache/models/Vector3f.java | 8 ++ .../runelite/cache/models/VertexNormal.java | 30 ++++++ .../java/net/runelite/modelviewer/Camera.java | 2 +- .../net/runelite/modelviewer/ModelViewer.java | 35 ++++-- 7 files changed, 178 insertions(+), 8 deletions(-) create mode 100644 cache/src/main/java/net/runelite/cache/models/FaceNormal.java create mode 100644 cache/src/main/java/net/runelite/cache/models/Vector3f.java create mode 100644 cache/src/main/java/net/runelite/cache/models/VertexNormal.java diff --git a/cache/src/main/java/net/runelite/cache/definitions/ModelDefinition.java b/cache/src/main/java/net/runelite/cache/definitions/ModelDefinition.java index eff96f563b..0a8a3bf166 100644 --- a/cache/src/main/java/net/runelite/cache/definitions/ModelDefinition.java +++ b/cache/src/main/java/net/runelite/cache/definitions/ModelDefinition.java @@ -1,5 +1,8 @@ package net.runelite.cache.definitions; +import net.runelite.cache.models.FaceNormal; +import net.runelite.cache.models.VertexNormal; + public class ModelDefinition { public short[] texTriangleX; @@ -41,5 +44,103 @@ public class ModelDefinition public int anInt2595; public int vertexCount = 0; public short[] texturePrimaryColor; + public VertexNormal[] normals; + public FaceNormal[] faceNormals; + + public void computeNormals() + { + if (this.normals != null) + { + return; + } + + this.normals = new VertexNormal[this.vertexCount]; + + int var1; + for (var1 = 0; var1 < this.vertexCount; ++var1) + { + this.normals[var1] = new VertexNormal(); + } + + for (var1 = 0; var1 < this.triangleFaceCount; ++var1) + { + int vertexA = this.trianglePointsX[var1]; + int vertexB = this.trianglePointsY[var1]; + int vertexC = this.trianglePointsZ[var1]; + + int xA = this.vertexX[vertexB] - this.vertexX[vertexA]; + int yA = this.vertexY[vertexB] - this.vertexY[vertexA]; + int zA = this.vertexZ[vertexB] - this.vertexZ[vertexA]; + + int xB = this.vertexX[vertexC] - this.vertexX[vertexA]; + int yB = this.vertexY[vertexC] - this.vertexY[vertexA]; + int zB = this.vertexZ[vertexC] - this.vertexZ[vertexA]; + + // Compute cross product + int var11 = yA * zB - yB * zA; + int var12 = zA * xB - zB * xA; + int var13 = xA * yB - xB * yA; + + while (var11 > 8192 || var12 > 8192 || var13 > 8192 || var11 < -8192 || var12 < -8192 || var13 < -8192) + { + var11 >>= 1; + var12 >>= 1; + var13 >>= 1; + } + + int length = (int) Math.sqrt((double) (var11 * var11 + var12 * var12 + var13 * var13)); + if (length <= 0) + { + length = 1; + } + + var11 = var11 * 256 / length; + var12 = var12 * 256 / length; + var13 = var13 * 256 / length; + + byte var15; + if (this.faceRenderType == null) + { + var15 = 0; + } + else + { + var15 = this.faceRenderType[var1]; + } + + if (var15 == 0) + { + VertexNormal var16 = this.normals[vertexA]; + var16.x += var11; + var16.y += var12; + var16.z += var13; + ++var16.magnitude; + + var16 = this.normals[vertexB]; + var16.x += var11; + var16.y += var12; + var16.z += var13; + ++var16.magnitude; + + var16 = this.normals[vertexC]; + var16.x += var11; + var16.y += var12; + var16.z += var13; + ++var16.magnitude; + } + else if (var15 == 1) + { + if (this.faceNormals == null) + { + this.faceNormals = new FaceNormal[this.triangleFaceCount]; + } + + FaceNormal var17 = this.faceNormals[var1] = new FaceNormal(); + var17.x = var11; + var17.y = var12; + var17.z = var13; + } + } + } } diff --git a/cache/src/main/java/net/runelite/cache/definitions/loaders/ModelLoader.java b/cache/src/main/java/net/runelite/cache/definitions/loaders/ModelLoader.java index 16e1676d74..efcd97bead 100644 --- a/cache/src/main/java/net/runelite/cache/definitions/loaders/ModelLoader.java +++ b/cache/src/main/java/net/runelite/cache/definitions/loaders/ModelLoader.java @@ -18,6 +18,8 @@ public class ModelLoader this.load2(def, var1); } + def.computeNormals(); + return def; } diff --git a/cache/src/main/java/net/runelite/cache/models/FaceNormal.java b/cache/src/main/java/net/runelite/cache/models/FaceNormal.java new file mode 100644 index 0000000000..387db6a335 --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/models/FaceNormal.java @@ -0,0 +1,8 @@ +package net.runelite.cache.models; + +public class FaceNormal +{ + public int x; + public int y; + public int z; +} diff --git a/cache/src/main/java/net/runelite/cache/models/Vector3f.java b/cache/src/main/java/net/runelite/cache/models/Vector3f.java new file mode 100644 index 0000000000..ad34a3f065 --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/models/Vector3f.java @@ -0,0 +1,8 @@ +package net.runelite.cache.models; + +public class Vector3f +{ + public float x; + public float y; + public float z; +} diff --git a/cache/src/main/java/net/runelite/cache/models/VertexNormal.java b/cache/src/main/java/net/runelite/cache/models/VertexNormal.java new file mode 100644 index 0000000000..b1635ed1c9 --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/models/VertexNormal.java @@ -0,0 +1,30 @@ +package net.runelite.cache.models; + +public class VertexNormal +{ + public int x; + public int y; + public int z; + public int magnitude; + + public Vector3f normalize() + { + Vector3f v = new Vector3f(); + + int length = (int) Math.sqrt((double) (x * x + y * y + z * z)); + if (length == 0) + { + length = 1; + } + + v.x = (float) x / length; + v.y = (float) y / length; + v.z = (float) z / length; + + assert v.x >= -1f && v.x <= 1f; + assert v.y >= -1f && v.y <= 1f; + assert v.z >= -1f && v.z <= 1f; + + return v; + } +} diff --git a/model-viewer/src/main/java/net/runelite/modelviewer/Camera.java b/model-viewer/src/main/java/net/runelite/modelviewer/Camera.java index aef196670e..6aea1aaa0c 100644 --- a/model-viewer/src/main/java/net/runelite/modelviewer/Camera.java +++ b/model-viewer/src/main/java/net/runelite/modelviewer/Camera.java @@ -107,7 +107,7 @@ public class Camera { Mouse.setGrabbed(true); } - if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) + if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE) || Keyboard.isKeyDown(Keyboard.KEY_LMENU)) { Mouse.setGrabbed(false); } diff --git a/model-viewer/src/main/java/net/runelite/modelviewer/ModelViewer.java b/model-viewer/src/main/java/net/runelite/modelviewer/ModelViewer.java index 98a33f1534..0456e0b502 100644 --- a/model-viewer/src/main/java/net/runelite/modelviewer/ModelViewer.java +++ b/model-viewer/src/main/java/net/runelite/modelviewer/ModelViewer.java @@ -40,6 +40,8 @@ import java.util.List; import net.runelite.cache.definitions.ModelDefinition; import net.runelite.cache.definitions.NpcDefinition; import net.runelite.cache.definitions.loaders.ModelLoader; +import net.runelite.cache.models.Vector3f; +import net.runelite.cache.models.VertexNormal; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.DefaultParser; @@ -116,16 +118,14 @@ public class ModelViewer GL11.glFrustum(-aspect * near * fov, aspect * near * fov, -fov, fov, near, far); GL11.glEnable(GL11.GL_DEPTH_TEST); + GL11.glCullFace(GL11.GL_BACK); + GL11.glEnable(GL11.GL_CULL_FACE); long last = 0; Camera camera = new Camera(); - GL11.glMatrixMode(GL11.GL_MODELVIEW); - glRotatef(45, 1, 0, 0); - GL11.glPopMatrix(); - while (!Display.isCloseRequested()) { // Clear the screen and depth buffer @@ -159,6 +159,19 @@ public class ModelViewer int vertexB = md.trianglePointsY[i]; int vertexC = md.trianglePointsZ[i]; + VertexNormal normalVertexA = md.normals[vertexA]; + VertexNormal normalVertexB = md.normals[vertexB]; + VertexNormal normalVertexC = md.normals[vertexC]; + + Vector3f nA = normalVertexA.normalize(); + Vector3f nB = normalVertexB.normalize(); + Vector3f nC = normalVertexC.normalize(); + + // Invert y + nA.y = -nA.y; + nB.y = -nB.y; + nC.y = -nC.y; + int vertexAx = md.vertexX[vertexA]; int vertexAy = md.vertexY[vertexA]; int vertexAz = md.vertexZ[vertexA]; @@ -195,9 +208,17 @@ public class ModelViewer GL11.glColor3f(rf, gf, bf); - GL11.glVertex3i(vertexAx, vertexAy, vertexAz); - GL11.glVertex3i(vertexBx, vertexBy, vertexBz); - GL11.glVertex3i(vertexCx, vertexCy, vertexCz); + // With GL11.GL_CCW we have to draw A -> C -> B when + // inverting y instead of A -> B -> C, or else with cull + // face will cull the wrong side + GL11.glNormal3f(nA.x, nA.y, nA.z); + GL11.glVertex3i(vertexAx, -vertexAy, vertexAz); + + GL11.glNormal3f(nC.x, nC.y, nC.z); + GL11.glVertex3i(vertexCx, -vertexCy, vertexCz); + + GL11.glNormal3f(nB.x, nB.y, nB.z); + GL11.glVertex3i(vertexBx, -vertexBy, vertexBz); } GL11.glEnd();