cache: add .obj model exporter

This commit is contained in:
Adam
2017-03-20 18:01:33 -04:00
parent 592a2502cf
commit da68089c18
6 changed files with 151 additions and 5 deletions

View File

@@ -5,6 +5,7 @@ import net.runelite.cache.models.VertexNormal;
public class ModelDefinition
{
public int id;
public short[] texTriangleX;
public int[] vertexX;
public byte[] faceRenderPriorities;
@@ -44,8 +45,8 @@ public class ModelDefinition
public int anInt2595;
public int vertexCount = 0;
public short[] texturePrimaryColor;
public VertexNormal[] normals;
public FaceNormal[] faceNormals;
public transient VertexNormal[] normals;
public transient FaceNormal[] faceNormals;
public void computeNormals()
{

View File

@@ -5,9 +5,10 @@ import net.runelite.cache.io.InputStream;
public class ModelLoader
{
public ModelDefinition load(byte[] var1)
public ModelDefinition load(int modelId, byte[] var1)
{
ModelDefinition def = new ModelDefinition();
def.id = modelId;
if (var1[var1.length - 1] == -1 && var1[var1.length - 2] == -1)
{

View File

@@ -0,0 +1,92 @@
/*
* 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;
import java.awt.Color;
import java.io.IOException;
import java.io.PrintWriter;
import net.runelite.cache.definitions.ModelDefinition;
public class ObjExporter
{
private final ModelDefinition model;
public ObjExporter(ModelDefinition model)
{
this.model = model;
}
public void export(PrintWriter objWriter, PrintWriter mtlWriter) throws IOException
{
model.computeNormals();
objWriter.println("mtllib " + model.id + ".mtl");
objWriter.println("o runescapemodel");
for (int i = 0; i < model.vertexCount; ++i)
{
objWriter.println(" v " + model.vertexX[i] + " " + model.vertexY[i] + " " + model.vertexZ[i]);
}
for (VertexNormal normal : model.normals)
{
objWriter.println(" vn " + normal.x + " " + normal.y + " " + normal.z);
}
for (int i = 0; i < model.triangleFaceCount; ++i)
{
objWriter.println(" usemtl color" + model.faceColor[i]);
objWriter.println(" f " + (model.trianglePointsX[i] + 1) + " " + (model.trianglePointsY[i] + 1) + " " + (model.trianglePointsZ[i] + 1));
objWriter.println("");
}
for (int i = 0; i < model.faceColor.length; ++i)
{
mtlWriter.println("newmtl color" + model.faceColor[i]);
Color color = rs2hsbToColor(model.faceColor[i]);
double r = color.getRed() / 255.0;
double g = color.getGreen() / 255.0;
double b = color.getBlue() / 255.0;
mtlWriter.println(" Kd " + r + " " + g + " " + b);
if (model.faceAlphas != null)
{
mtlWriter.println(" d " + (model.faceAlphas[i] & 0xFF) / 255.0);
}
}
}
private static Color rs2hsbToColor(int hsb)
{
int decode_hue = (hsb >> 10) & 0x3f;
int decode_saturation = (hsb >> 7) & 0x07;
int decode_brightness = (hsb & 0x7f);
return Color.getHSBColor((float) decode_hue / 63, (float) decode_saturation / 7, (float) decode_brightness / 127);
}
}

View File

@@ -69,7 +69,7 @@ public class ModelDumperTest
byte[] contents = file.getContents();
ModelLoader loader = new ModelLoader();
loader.load(contents);
loader.load(archive.getArchiveId(), contents);
Files.write(contents, new java.io.File(modelDir, archive.getArchiveId() + ".model"));
//Files.write(gson.toJson(loader), new java.io.File(modelDir, archive.getArchiveId() + ".json"), Charset.defaultCharset());

View File

@@ -0,0 +1,52 @@
/*
* 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;
import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.nio.file.Files;
import net.runelite.cache.definitions.ModelDefinition;
import net.runelite.cache.definitions.loaders.ModelLoader;
import org.junit.Ignore;
import org.junit.Test;
public class ObjExporterTest
{
@Test
@Ignore
public void testExport() throws Exception
{
ModelLoader loader = new ModelLoader();
ModelDefinition model = loader.load(11048, Files.readAllBytes(new File("D:\\rs\\07\\cache\\models\\11048.model").toPath()));
ObjExporter exporter = new ObjExporter(model);
try (PrintWriter objWriter = new PrintWriter(new FileWriter(new File("C:\\rs\\temp\\11048.obj")));
PrintWriter mtlWriter = new PrintWriter(new FileWriter(new File("C:\\rs\\temp\\11048.mtl"))))
{
exporter.export(objWriter, mtlWriter);
}
}
}

View File

@@ -558,7 +558,7 @@ public class ModelViewer
{
ModelLoader loader = new ModelLoader();
byte[] b = Files.readAllBytes(new File("models/" + id + ".model").toPath());
md = loader.load(b);
md = loader.load(id, b);
models[id] = md;
return md;
}