model-viewer: fix some of the orientation issues
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
package net.runelite.cache.definitions;
|
||||
|
||||
import java.util.Arrays;
|
||||
import net.runelite.cache.models.CircularAngle;
|
||||
import net.runelite.cache.models.FaceNormal;
|
||||
import net.runelite.cache.models.VertexNormal;
|
||||
|
||||
@@ -153,7 +155,8 @@ public class ModelDefinition
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the UV coordinates for every three-vertex face that has a texture.
|
||||
* Computes the UV coordinates for every three-vertex face that has a
|
||||
* texture.
|
||||
*/
|
||||
public void computeTextureUVCoordinates()
|
||||
{
|
||||
@@ -266,4 +269,80 @@ public class ModelDefinition
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void rotate(int orientation)
|
||||
{
|
||||
int sin = CircularAngle.SINE[orientation];
|
||||
int cos = CircularAngle.COSINE[orientation];
|
||||
|
||||
assert vertexPositionsX.length == vertexPositionsY.length;
|
||||
assert vertexPositionsY.length == vertexPositionsZ.length;
|
||||
|
||||
for (int i = 0; i < vertexPositionsX.length; ++i)
|
||||
{
|
||||
vertexPositionsX[i] = vertexPositionsX[i] * cos + vertexPositionsZ[i] * sin >> 16;
|
||||
vertexPositionsZ[i] = vertexPositionsZ[i] * cos - vertexPositionsX[i] * sin >> 16;
|
||||
}
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
public void method1493()
|
||||
{
|
||||
int var1;
|
||||
for (var1 = 0; var1 < this.vertexCount; ++var1)
|
||||
{
|
||||
this.vertexPositionsZ[var1] = -this.vertexPositionsZ[var1];
|
||||
}
|
||||
|
||||
for (var1 = 0; var1 < this.faceCount; ++var1)
|
||||
{
|
||||
int var2 = this.faceVertexIndices1[var1];
|
||||
this.faceVertexIndices1[var1] = this.faceVertexIndices3[var1];
|
||||
this.faceVertexIndices3[var1] = var2;
|
||||
}
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
public void rotate1()
|
||||
{
|
||||
for (int var1 = 0; var1 < this.vertexCount; ++var1)
|
||||
{
|
||||
int var2 = this.vertexPositionsX[var1];
|
||||
this.vertexPositionsX[var1] = this.vertexPositionsZ[var1];
|
||||
this.vertexPositionsZ[var1] = -var2;
|
||||
}
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
public void rotate2()
|
||||
{
|
||||
for (int var1 = 0; var1 < this.vertexCount; ++var1)
|
||||
{
|
||||
this.vertexPositionsX[var1] = -this.vertexPositionsX[var1];
|
||||
this.vertexPositionsZ[var1] = -this.vertexPositionsZ[var1];
|
||||
}
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
public void rotate3()
|
||||
{
|
||||
for (int var1 = 0; var1 < this.vertexCount; ++var1)
|
||||
{
|
||||
int var2 = this.vertexPositionsZ[var1];
|
||||
this.vertexPositionsZ[var1] = this.vertexPositionsX[var1];
|
||||
this.vertexPositionsX[var1] = -var2;
|
||||
}
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
private void reset()
|
||||
{
|
||||
faceNormals = null;
|
||||
faceTextureUCoordinates = faceTextureVCoordinates = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ public class ObjectDefinition
|
||||
private int anInt2105 = -1;
|
||||
private int anInt2106 = -1;
|
||||
private int[] configChangeDest;
|
||||
private boolean aBool2108 = false;
|
||||
private boolean isRotated = false;
|
||||
private int configId = -1;
|
||||
private int anInt2110 = -1;
|
||||
private boolean aBool2111 = false;
|
||||
@@ -434,14 +434,14 @@ public class ObjectDefinition
|
||||
this.configChangeDest = configChangeDest;
|
||||
}
|
||||
|
||||
public boolean isaBool2108()
|
||||
public boolean isRotated()
|
||||
{
|
||||
return aBool2108;
|
||||
return isRotated;
|
||||
}
|
||||
|
||||
public void setaBool2108(boolean aBool2108)
|
||||
public void setIsRotated(boolean isRotated)
|
||||
{
|
||||
this.aBool2108 = aBool2108;
|
||||
this.isRotated = isRotated;
|
||||
}
|
||||
|
||||
public int getConfigId()
|
||||
|
||||
@@ -199,7 +199,7 @@ public class ObjectLoader
|
||||
}
|
||||
else if (62 == opcode)
|
||||
{
|
||||
def.setaBool2108(true);
|
||||
def.setIsRotated(true);
|
||||
}
|
||||
else if (opcode == 64)
|
||||
{
|
||||
|
||||
42
cache/src/main/java/net/runelite/cache/models/CircularAngle.java
vendored
Normal file
42
cache/src/main/java/net/runelite/cache/models/CircularAngle.java
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.models;
|
||||
|
||||
public class CircularAngle
|
||||
{
|
||||
private static final double UNIT = Math.PI / 1024d; // How much of the circle each unit of SINE/COSINE is
|
||||
|
||||
public static final int[] SINE = new int[2048]; // sine angles for each of the 2048 units, * 65536 and stored as an int
|
||||
public static final int[] COSINE = new int[2048]; // cosine
|
||||
|
||||
static
|
||||
{
|
||||
for (int i = 0; i < 2048; ++i)
|
||||
{
|
||||
SINE[i] = (int) (65536.0D * Math.sin((double) i * UNIT));
|
||||
COSINE[i] = (int) (65536.0D * Math.cos((double) i * UNIT));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.modelviewer;
|
||||
|
||||
public class LocationKey
|
||||
{
|
||||
private final int id;
|
||||
private final int type;
|
||||
private final int orientation;
|
||||
|
||||
public LocationKey(int id, int type, int orientation)
|
||||
{
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
this.orientation = orientation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int hash = 5;
|
||||
hash = 97 * hash + this.id;
|
||||
hash = 97 * hash + this.type;
|
||||
hash = 97 * hash + this.orientation;
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
final LocationKey other = (LocationKey) obj;
|
||||
if (this.id != other.id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (this.type != other.type)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (this.orientation != other.orientation)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.modelviewer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import net.runelite.cache.definitions.ModelDefinition;
|
||||
import net.runelite.cache.definitions.ObjectDefinition;
|
||||
import net.runelite.cache.definitions.loaders.ModelLoader;
|
||||
import net.runelite.cache.region.Location;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ModelManager
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(ModelManager.class);
|
||||
|
||||
private static Map<LocationKey, ModelDefinition> models = new HashMap<>();
|
||||
|
||||
public static ModelDefinition getModel(int id, ObjectDefinition object, Location location)
|
||||
{
|
||||
LocationKey key;
|
||||
|
||||
if (location != null)
|
||||
{
|
||||
key = new LocationKey(id, location.getType(), location.getOrientation());
|
||||
}
|
||||
else
|
||||
{
|
||||
key = new LocationKey(id, -1, -1);
|
||||
}
|
||||
|
||||
ModelDefinition md = models.get(key);
|
||||
if (md != null)
|
||||
{
|
||||
return md;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
byte[] b = Files.readAllBytes(new File("models/" + id + ".model").toPath());
|
||||
|
||||
ModelLoader loader = new ModelLoader();
|
||||
md = loader.load(id, b);
|
||||
|
||||
rotate(md, object, location);
|
||||
|
||||
models.put(key, md);
|
||||
return md;
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.warn(null, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// this logic is from method3697 in 140
|
||||
private static void rotate(ModelDefinition md, ObjectDefinition object, Location location)
|
||||
{
|
||||
if (object.getObjectTypes() == null)
|
||||
{
|
||||
boolean isRotate = object.isRotated();
|
||||
|
||||
if (location.getType() == 2 && location.getOrientation() > 3)
|
||||
{
|
||||
isRotate = !isRotate;
|
||||
}
|
||||
|
||||
if (isRotate)
|
||||
{
|
||||
md.method1493();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
boolean isRotate = object.isRotated() ^ location.getOrientation() > 3;
|
||||
|
||||
if (isRotate)
|
||||
{
|
||||
md.method1493();
|
||||
}
|
||||
}
|
||||
|
||||
switch (location.getOrientation())
|
||||
{
|
||||
case 1:
|
||||
md.rotate1();
|
||||
break;
|
||||
case 2:
|
||||
md.rotate2();
|
||||
break;
|
||||
case 3:
|
||||
md.rotate3();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,13 +27,11 @@ package net.runelite.modelviewer;
|
||||
import com.google.gson.Gson;
|
||||
import java.awt.Color;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -45,7 +43,6 @@ import net.runelite.cache.definitions.ObjectDefinition;
|
||||
import net.runelite.cache.definitions.OverlayDefinition;
|
||||
import net.runelite.cache.definitions.TextureDefinition;
|
||||
import net.runelite.cache.definitions.UnderlayDefinition;
|
||||
import net.runelite.cache.definitions.loaders.ModelLoader;
|
||||
import net.runelite.cache.models.Vector3f;
|
||||
import net.runelite.cache.models.VertexNormal;
|
||||
import net.runelite.cache.region.Location;
|
||||
@@ -78,7 +75,6 @@ public class ModelViewer
|
||||
private static final int NUM_OVERLAYS = 174;
|
||||
private static final int NUM_TEXTURES = 61;
|
||||
private static final int NUM_OBJECTS = 28598;
|
||||
private static final int NUM_MODELS = 31247;
|
||||
|
||||
/**
|
||||
* size of a tile in local coordinates
|
||||
@@ -91,7 +87,6 @@ public class ModelViewer
|
||||
|
||||
private static Map<Integer, Texture> textures = new HashMap<>();
|
||||
private static ObjectDefinition[] objects = new ObjectDefinition[NUM_OBJECTS];
|
||||
private static ModelDefinition[] models = new ModelDefinition[NUM_MODELS];
|
||||
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
@@ -124,7 +119,7 @@ public class ModelViewer
|
||||
// render model
|
||||
String model = cmd.getOptionValue("model");
|
||||
|
||||
ModelDefinition md = getModel(Integer.parseInt(model));
|
||||
ModelDefinition md = ModelManager.getModel(Integer.parseInt(model), null, null);
|
||||
models.add(md);
|
||||
}
|
||||
if (cmd.hasOption("npc"))
|
||||
@@ -138,7 +133,7 @@ public class ModelViewer
|
||||
|
||||
for (int model : npcdef.models)
|
||||
{
|
||||
ModelDefinition md = getModel(model);
|
||||
ModelDefinition md = ModelManager.getModel(model, null, null);
|
||||
models.add(md);
|
||||
}
|
||||
}
|
||||
@@ -153,7 +148,7 @@ public class ModelViewer
|
||||
|
||||
for (int model : objdef.getObjectModels())
|
||||
{
|
||||
ModelDefinition md = getModel(model);
|
||||
ModelDefinition md = ModelManager.getModel(model, null, null);
|
||||
models.add(md);
|
||||
}
|
||||
}
|
||||
@@ -301,6 +296,9 @@ public class ModelViewer
|
||||
Texture texture = getTexture(textureId);
|
||||
assert texture != null;
|
||||
|
||||
if (md.faceTextureUCoordinates == null || md.faceTextureVCoordinates == null)
|
||||
md.computeTextureUVCoordinates();
|
||||
|
||||
u = md.faceTextureUCoordinates[i];
|
||||
v = md.faceTextureVCoordinates[i];
|
||||
|
||||
@@ -529,7 +527,6 @@ public class ModelViewer
|
||||
int regionY = objectPos.getY() - region.getBaseY();
|
||||
int height = -region.getTileHeight(objectPos.getZ(), regionX, regionY) / HEIGHT_MOD;
|
||||
|
||||
//byte overlayRotation = region.getOverlayRotation(objectPos.getZ(), regionX, regionY);
|
||||
GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
|
||||
// TILE_SCALE/2 to draw the object from the center of the tile it is on
|
||||
@@ -537,14 +534,11 @@ public class ModelViewer
|
||||
|
||||
for (int i = 0; i < object.getObjectModels().length; ++i)
|
||||
{
|
||||
ModelDefinition md = getModel(object.getObjectModels()[i]);
|
||||
ModelDefinition md = ModelManager.getModel(object.getObjectModels()[i], object, location);
|
||||
|
||||
if (object.getObjectTypes() != null)
|
||||
if (object.getObjectTypes() != null && object.getObjectTypes()[i] != location.getType())
|
||||
{
|
||||
if (object.getObjectTypes()[i] != location.getType())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
drawModel(md, object.getRecolorToFind(), object.getRecolorToReplace());
|
||||
@@ -606,31 +600,6 @@ public class ModelViewer
|
||||
}
|
||||
}
|
||||
|
||||
private static ModelDefinition getModel(int id)
|
||||
{
|
||||
ModelDefinition md = models[id];
|
||||
if (md != null)
|
||||
{
|
||||
return md;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
byte[] b = Files.readAllBytes(new File("models/" + id + ".model").toPath());
|
||||
|
||||
ModelLoader loader = new ModelLoader();
|
||||
md = loader.load(id, b);
|
||||
|
||||
models[id] = md;
|
||||
return md;
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.warn(null, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Texture getTexture(int id)
|
||||
{
|
||||
Texture texture = textures.get(id);
|
||||
|
||||
Reference in New Issue
Block a user