From aa30d2c7827cc2aef92fdd84abed8693285d3273 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 20 May 2018 20:15:37 -0400 Subject: [PATCH] modelviewer: begin work on tile shapes --- .../net/runelite/cache/OverlayManager.java | 80 +++ .../net/runelite/cache/UnderlayManager.java | 80 +++ .../providers/OverlayProvider.java | 32 ++ .../providers/UnderlayProvider.java | 32 ++ .../net/runelite/modelviewer/ModelViewer.java | 530 +++++++++--------- .../java/net/runelite/modelviewer/Scene.java | 367 ++++++++++++ .../runelite/modelviewer/SceneTileModel.java | 305 ++++++++++ .../runelite/modelviewer/SceneTilePaint.java | 34 ++ 8 files changed, 1185 insertions(+), 275 deletions(-) create mode 100644 cache/src/main/java/net/runelite/cache/OverlayManager.java create mode 100644 cache/src/main/java/net/runelite/cache/UnderlayManager.java create mode 100644 cache/src/main/java/net/runelite/cache/definitions/providers/OverlayProvider.java create mode 100644 cache/src/main/java/net/runelite/cache/definitions/providers/UnderlayProvider.java create mode 100644 model-viewer/src/main/java/net/runelite/modelviewer/Scene.java create mode 100644 model-viewer/src/main/java/net/runelite/modelviewer/SceneTileModel.java create mode 100644 model-viewer/src/main/java/net/runelite/modelviewer/SceneTilePaint.java diff --git a/cache/src/main/java/net/runelite/cache/OverlayManager.java b/cache/src/main/java/net/runelite/cache/OverlayManager.java new file mode 100644 index 0000000000..6940227c0f --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/OverlayManager.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, Adam + * 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; + +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import net.runelite.cache.definitions.OverlayDefinition; +import net.runelite.cache.definitions.loaders.OverlayLoader; +import net.runelite.cache.definitions.providers.OverlayProvider; +import net.runelite.cache.fs.Archive; +import net.runelite.cache.fs.ArchiveFiles; +import net.runelite.cache.fs.FSFile; +import net.runelite.cache.fs.Index; +import net.runelite.cache.fs.Storage; +import net.runelite.cache.fs.Store; + +public class OverlayManager implements OverlayProvider +{ + private final Store store; + private final Map overlays = new HashMap<>(); + + public OverlayManager(Store store) + { + this.store = store; + } + + public void load() throws IOException + { + Storage storage = store.getStorage(); + Index index = store.getIndex(IndexType.CONFIGS); + Archive archive = index.getArchive(ConfigType.OVERLAY.getId()); + + byte[] archiveData = storage.loadArchive(archive); + ArchiveFiles files = archive.getFiles(archiveData); + + for (FSFile file : files.getFiles()) + { + OverlayLoader loader = new OverlayLoader(); + OverlayDefinition overlay = loader.load(file.getFileId(), file.getContents()); + + overlays.put(overlay.getId(), overlay); + } + } + + public Collection getOverlays() + { + return Collections.unmodifiableCollection(overlays.values()); + } + + @Override + public OverlayDefinition provide(int overlayId) + { + return overlays.get(overlayId); + } +} diff --git a/cache/src/main/java/net/runelite/cache/UnderlayManager.java b/cache/src/main/java/net/runelite/cache/UnderlayManager.java new file mode 100644 index 0000000000..3bba2230a4 --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/UnderlayManager.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, Adam + * 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; + +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import net.runelite.cache.definitions.UnderlayDefinition; +import net.runelite.cache.definitions.loaders.UnderlayLoader; +import net.runelite.cache.definitions.providers.UnderlayProvider; +import net.runelite.cache.fs.Archive; +import net.runelite.cache.fs.ArchiveFiles; +import net.runelite.cache.fs.FSFile; +import net.runelite.cache.fs.Index; +import net.runelite.cache.fs.Storage; +import net.runelite.cache.fs.Store; + +public class UnderlayManager implements UnderlayProvider +{ + private final Store store; + private final Map underlays = new HashMap<>(); + + public UnderlayManager(Store store) + { + this.store = store; + } + + public void load() throws IOException + { + Storage storage = store.getStorage(); + Index index = store.getIndex(IndexType.CONFIGS); + Archive archive = index.getArchive(ConfigType.UNDERLAY.getId()); + + byte[] archiveData = storage.loadArchive(archive); + ArchiveFiles files = archive.getFiles(archiveData); + + for (FSFile file : files.getFiles()) + { + UnderlayLoader loader = new UnderlayLoader(); + UnderlayDefinition underlay = loader.load(file.getFileId(), file.getContents()); + + underlays.put(underlay.getId(), underlay); + } + } + + public Collection getUnderlays() + { + return Collections.unmodifiableCollection(underlays.values()); + } + + @Override + public UnderlayDefinition provide(int underlayId) + { + return underlays.get(underlayId); + } +} diff --git a/cache/src/main/java/net/runelite/cache/definitions/providers/OverlayProvider.java b/cache/src/main/java/net/runelite/cache/definitions/providers/OverlayProvider.java new file mode 100644 index 0000000000..a793b39962 --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/definitions/providers/OverlayProvider.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, Adam + * 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.definitions.providers; + +import net.runelite.cache.definitions.OverlayDefinition; + +public interface OverlayProvider +{ + OverlayDefinition provide(int overlayId); +} diff --git a/cache/src/main/java/net/runelite/cache/definitions/providers/UnderlayProvider.java b/cache/src/main/java/net/runelite/cache/definitions/providers/UnderlayProvider.java new file mode 100644 index 0000000000..3b0381c7a3 --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/definitions/providers/UnderlayProvider.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, Adam + * 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.definitions.providers; + +import net.runelite.cache.definitions.UnderlayDefinition; + +public interface UnderlayProvider +{ + UnderlayDefinition provide(int underlayId); +} 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 47c4e426ec..759dbae155 100644 --- a/model-viewer/src/main/java/net/runelite/modelviewer/ModelViewer.java +++ b/model-viewer/src/main/java/net/runelite/modelviewer/ModelViewer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017, Adam + * Copyright (c) 2016-2018, Adam * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,10 +26,8 @@ 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.util.ArrayList; @@ -37,28 +35,36 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.imageio.ImageIO; +import net.runelite.cache.IndexType; +import net.runelite.cache.ObjectManager; +import net.runelite.cache.OverlayManager; +import net.runelite.cache.SpriteManager; +import net.runelite.cache.TextureManager; +import net.runelite.cache.UnderlayManager; import net.runelite.cache.definitions.KitDefinition; import net.runelite.cache.definitions.LocationsDefinition; import net.runelite.cache.definitions.MapDefinition; import net.runelite.cache.definitions.ModelDefinition; import net.runelite.cache.definitions.NpcDefinition; import net.runelite.cache.definitions.ObjectDefinition; -import net.runelite.cache.definitions.OverlayDefinition; +import net.runelite.cache.definitions.SpriteDefinition; import net.runelite.cache.definitions.TextureDefinition; -import net.runelite.cache.definitions.UnderlayDefinition; import net.runelite.cache.definitions.loaders.LocationsLoader; import net.runelite.cache.definitions.loaders.MapLoader; +import net.runelite.cache.fs.Archive; +import net.runelite.cache.fs.Index; +import net.runelite.cache.fs.Storage; +import net.runelite.cache.fs.Store; import net.runelite.cache.models.Vector3f; import net.runelite.cache.models.VertexNormal; import net.runelite.cache.region.Location; import net.runelite.cache.region.Position; import net.runelite.cache.region.Region; +import net.runelite.cache.util.XteaKeyManager; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.DefaultParser; import org.apache.commons.cli.Options; -import org.apache.commons.compress.utils.IOUtils; import org.lwjgl.opengl.Display; import org.lwjgl.opengl.DisplayMode; import org.lwjgl.opengl.GL11; @@ -77,27 +83,24 @@ public class ModelViewer { private static final Logger logger = LoggerFactory.getLogger(ModelViewer.class); - private static final int NUM_UNDERLAYS = 150; - private static final int NUM_OVERLAYS = 174; - private static final int NUM_TEXTURES = 61; - private static final int NUM_OBJECTS = 28598; - /** * size of a tile in local coordinates */ private static final int TILE_SCALE = 128; private static final int HEIGHT_MOD = 4; - private static UnderlayDefinition[] underlays = new UnderlayDefinition[NUM_UNDERLAYS]; - private static OverlayDefinition[] overlays = new OverlayDefinition[NUM_OVERLAYS]; + private static ObjectManager objectManager; + private static TextureManager textureManager; + private static SpriteManager spriteManager; private static Map textures = new HashMap<>(); - private static ObjectDefinition[] objects = new ObjectDefinition[NUM_OBJECTS]; public static void main(String[] args) throws Exception { Options options = new Options(); + options.addOption(null, "store", true, "store directory"); + options.addOption(null, "npcdir", true, "npc directory"); options.addOption(null, "mapdir", true, "maps directory"); options.addOption(null, "objectdir", true, "objects directory"); @@ -117,10 +120,33 @@ public class ModelViewer NpcDefinition npcdef = null; ObjectDefinition objdef = null; + Store store = null; + UnderlayManager underlayManager = null; + OverlayManager overlayManager = null; List models = new ArrayList<>(); Region region = null; + if (cmd.hasOption("store")) + { + store = new Store(new File(cmd.getOptionValue("store"))); + store.load(); + + underlayManager = new UnderlayManager(store); + underlayManager.load(); + + overlayManager = new OverlayManager(store); + overlayManager.load(); + + objectManager = new ObjectManager(store); + objectManager.load(); + + textureManager = new TextureManager(store); + textureManager.load(); + + spriteManager = new SpriteManager(store); + spriteManager.load(); + } if (cmd.hasOption("model")) { // render model @@ -166,30 +192,31 @@ public class ModelViewer int x = Integer.parseInt(s[0]), y = Integer.parseInt(s[1]); + XteaKeyManager keyManager = new XteaKeyManager(); + keyManager.loadKeys(); + + int[] keys = keyManager.getKeys(x << 8 | y); + + Storage storage = store.getStorage(); + Index index = store.getIndex(IndexType.MAPS); + + Archive mapArchive = index.findArchiveByName("m" + x + "_" + y); + Archive locationsArchive = index.findArchiveByName("l" + x + "_" + y); + region = new Region(x, y); + + byte[] mapData = mapArchive.decompress(storage.loadArchive(mapArchive)); MapLoader mapLoader = new MapLoader(); - LocationsLoader locationsLoader = new LocationsLoader(); + MapDefinition mapDef = mapLoader.load(x, y, mapData); + region.loadTerrain(mapDef); - try (FileInputStream fin = new FileInputStream(mapdir + "/m" + x + "_" + y + ".dat")) + if (keys != null) { - byte[] b = IOUtils.toByteArray(fin); - MapDefinition mapDef = mapLoader.load(x, y, b); - region.loadTerrain(mapDef); - } - - try (FileInputStream fin = new FileInputStream(mapdir + "/l" + x + "_" + y + ".dat")) - { - byte[] b = IOUtils.toByteArray(fin); - LocationsDefinition locDef = locationsLoader.load(x, y, b); + byte[] locationData = locationsArchive.decompress(storage.loadArchive(locationsArchive), keys); + LocationsLoader locationsLoader = new LocationsLoader(); + LocationsDefinition locDef = locationsLoader.load(x, y, locationData); region.loadLocations(locDef); } - catch (FileNotFoundException ex) - { - logger.info("No landscape file for {},{}", x, y); - } - - loadUnderlays(); - loadOverlays(); } if (cmd.hasOption("kits")) { @@ -232,6 +259,8 @@ public class ModelViewer long last = 0; Camera camera = new Camera(); + Scene scene = new Scene(underlayManager, overlayManager); + scene.loadRegion(region); while (!Display.isCloseRequested()) { @@ -255,10 +284,11 @@ public class ModelViewer drawModel(def, recolourToFind, recolourToReplace); } - drawRegion(region); + drawScene(region, scene); + //drawRegion(region); Display.update(); - Display.sync(50); // fps + Display.sync(20); // fps long delta = System.currentTimeMillis() - last; last = System.currentTimeMillis(); @@ -410,139 +440,159 @@ public class ModelViewer } } - private static void drawRegion(Region region) + private static void drawScene(Region region, Scene scene) { - if (region == null) + for (int z = 0; z < Region.Z; ++z) + { + SceneTileModel[][] sceneTileModels = scene.getSceneTiles()[z]; + SceneTilePaint[][] sceneTilePaint = scene.getSceneTilePaint()[z]; + + for (int x = 0; x < Region.X; ++x) + { + for (int y = 0; y < Region.Y; ++y) + { + drawSceneTileModel(region, x, y, z, sceneTileModels[x][y]); + drawSceneTilePaint(region, x, y, z, sceneTilePaint[x][y]); + } + } + } + drawLocations(region); + + } + + private static void drawSceneTilePaint(Region region, int regionX, int regionY, int z, SceneTilePaint sceneTilePaint) + { + if (sceneTilePaint == null) { return; } - for (int regionX = 0; regionX < Region.X; ++regionX) + int glTexture = -1; + + Color color; + + if (sceneTilePaint.texture > -1) { - for (int regionY = 0; regionY < Region.Y; ++regionY) - { - int x = regionX; - int y = regionY; + color = Color.WHITE; - x *= TILE_SCALE; - y *= TILE_SCALE; + Texture texture = getTexture(sceneTilePaint.texture); + glTexture = texture.getOpenglId(); + assert glTexture > -1; - /* - Split into two triangles with vertices - x,y,z1 x+1,y,z2 x,y+1,z3 - x,y+1,z3 x+1,y,z2 x+1,y+1,z4 - - z1 = height - z2 = height of tile x+1 - z3 = height of tile y-1 - - in rs 0,0 (x,y) is the bottom left with - y increasing going further from you - - in opengl, 0,0 (x,z) is the bottom left - with z decreasing going further from you - - in rs, height is also negative - - so we do rs(x,y,z) -> opengl(x,-z,-y) - */ - int z1 = -region.getTileHeight(0, regionX, regionY); - int z2 = regionX + 1 < Region.X ? -region.getTileHeight(0, regionX + 1, regionY) : z1; - int z3 = regionY + 1 < Region.Y ? -region.getTileHeight(0, regionX, regionY + 1) : z1; - int z4 = regionX + 1 < Region.X && regionY + 1 < Region.Y ? -region.getTileHeight(0, regionX + 1, regionY + 1) : z1; - - // scale down height - z1 /= HEIGHT_MOD; - z2 /= HEIGHT_MOD; - z3 /= HEIGHT_MOD; - z4 /= HEIGHT_MOD; - - int underlayId = region.getUnderlayId(0, regionX, regionY); - int overlayId = region.getOverlayId(0, regionX, regionY); - - Color color = null; - int glTexture = -1; - - if (underlayId > 0) - { - UnderlayDefinition ud = underlays[underlayId - 1]; - color = new Color(ud.getColor()); - } - if (overlayId > 0) - { - OverlayDefinition od = overlays[overlayId - 1]; - color = new Color(od.getRgbColor()); - - if (od.getSecondaryRgbColor() > -1) - { - color = new Color(od.getSecondaryRgbColor()); - } - - if (od.getTexture() > -1) - { - color = Color.WHITE; - - Texture texture = getTexture(od.getTexture()); - glTexture = texture.getOpenglId(); - assert glTexture > -1; - - GL11.glEnable(GL11.GL_TEXTURE_2D); - GL11.glBindTexture(GL11.GL_TEXTURE_2D, glTexture); - } - } - - GL11.glBegin(GL11.GL_TRIANGLES); - - if (color != null) - { - GL11.glColor3f((float) color.getRed() / 255f, (float) color.getGreen() / 255f, (float) color.getBlue() / 255f); - } - - // triangle 1 - if (glTexture > -1) - { - GL11.glTexCoord2f(0, 0); - } - GL11.glVertex3i(x, z1, -y); - if (glTexture > -1) - { - GL11.glTexCoord2f(1, 0); - } - GL11.glVertex3i(x + TILE_SCALE, z2, -y); - if (glTexture > -1) - { - GL11.glTexCoord2f(0, 1); - } - GL11.glVertex3i(x, z3, -(y + TILE_SCALE)); - - // triangle 2 - if (glTexture > -1) - { - GL11.glTexCoord2f(0, 1); - } - GL11.glVertex3i(x, z3, -(y + TILE_SCALE)); - if (glTexture > -1) - { - GL11.glTexCoord2f(1, 0); - } - GL11.glVertex3i(x + TILE_SCALE, z2, -y); - if (glTexture > -1) - { - GL11.glTexCoord2f(1, 1); - } - GL11.glVertex3i(x + TILE_SCALE, z4, -(y + TILE_SCALE)); - - GL11.glEnd(); - - if (glTexture > -1) - { - GL11.glDisable(GL11.GL_TEXTURE_2D); - } - - } + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glBindTexture(GL11.GL_TEXTURE_2D, glTexture); + } + else + { + color = new Color(RS2HSB_to_RGB(sceneTilePaint.color)); } - drawLocations(region); + + GL11.glBegin(GL11.GL_TRIANGLES); + + int x = regionX * TILE_SCALE; + int y = regionY * TILE_SCALE; + + GL11.glColor3f((float) color.getRed() / 255f, (float) color.getGreen() / 255f, (float) color.getBlue() / 255f); + int z1 = -region.getTileHeight(z, regionX, regionY); + int z2 = regionX + 1 < Region.X ? -region.getTileHeight(z, regionX + 1, regionY) : z1; + int z3 = regionY + 1 < Region.Y ? -region.getTileHeight(z, regionX, regionY + 1) : z1; + int z4 = regionX + 1 < Region.X && regionY + 1 < Region.Y ? -region.getTileHeight(z, regionX + 1, regionY + 1) : z1; + + // triangle 1 + if (glTexture > -1) + { + GL11.glTexCoord2f(0, 0); + } + GL11.glVertex3i(x, z1, -y); + if (glTexture > -1) + { + GL11.glTexCoord2f(1, 0); + } + GL11.glVertex3i(x + TILE_SCALE, z2, -y); + if (glTexture > -1) + { + GL11.glTexCoord2f(0, 1); + } + GL11.glVertex3i(x, z3, -(y + TILE_SCALE)); + + // triangle 2 + if (glTexture > -1) + { + GL11.glTexCoord2f(0, 1); + } + GL11.glVertex3i(x, z3, -(y + TILE_SCALE)); + if (glTexture > -1) + { + GL11.glTexCoord2f(1, 0); + } + GL11.glVertex3i(x + TILE_SCALE, z2, -y); + if (glTexture > -1) + { + GL11.glTexCoord2f(1, 1); + } + GL11.glVertex3i(x + TILE_SCALE, z4, -(y + TILE_SCALE)); + + GL11.glEnd(); + + if (glTexture > -1) + { + GL11.glDisable(GL11.GL_TEXTURE_2D); + } + } + + private static void drawSceneTileModel(Region region, int regionX, int regionY, int z, SceneTileModel sceneTileModel) + { + if (sceneTileModel == null) + { + return; + } + + for (int i = 0; i < sceneTileModel.faceX.length; ++i) + { + int vertexA = sceneTileModel.faceX[i]; + int vertexB = sceneTileModel.faceY[i]; + int vertexC = sceneTileModel.faceZ[i]; + + int vertexAx = sceneTileModel.vertexX[vertexA]; + int vertexAy = sceneTileModel.vertexY[vertexA]; + int vertexAz = sceneTileModel.vertexZ[vertexA]; + + int vertexBx = sceneTileModel.vertexX[vertexB]; + int vertexBy = sceneTileModel.vertexY[vertexB]; + int vertexBz = sceneTileModel.vertexZ[vertexB]; + + int vertexCx = sceneTileModel.vertexX[vertexC]; + int vertexCy = sceneTileModel.vertexY[vertexC]; + int vertexCz = sceneTileModel.vertexZ[vertexC]; + + int colorA = sceneTileModel.triangleColorA[i]; + int colorB = sceneTileModel.triangleColorB[i]; + int colorC = sceneTileModel.triangleColorC[i]; + + Color color = null; + int glTexture = -1; + + color = new Color(RS2HSB_to_RGB(colorA)); + + GL11.glBegin(GL11.GL_TRIANGLES); + + if (color != null) + { + GL11.glColor3f((float) color.getRed() / 255f, (float) color.getGreen() / 255f, (float) color.getBlue() / 255f); + } + + GL11.glVertex3i(vertexAx, -vertexAy, -vertexAz); + GL11.glVertex3i(vertexBx, -vertexBy, -vertexBz); + GL11.glVertex3i(vertexCx, -vertexCy, -vertexCz); + + GL11.glEnd(); + + if (glTexture > -1) + { + GL11.glDisable(GL11.GL_TEXTURE_2D); + } + } } private static void drawLocations(Region region) @@ -559,18 +609,13 @@ public class ModelViewer Position objectPos = location.getPosition(); - if (location.getPosition().getZ() != 0) - { - continue; - } - int regionX = objectPos.getX() - region.getBaseX(); int regionY = objectPos.getY() - region.getBaseY(); - int height = -region.getTileHeight(objectPos.getZ(), regionX, regionY) / HEIGHT_MOD; + int height = -region.getTileHeight(objectPos.getZ(), regionX, regionY); // / HEIGHT_MOD; GL11.glMatrixMode(GL11.GL_MODELVIEW); // TILE_SCALE/2 to draw the object from the center of the tile it is on - GL11.glTranslatef(regionX * TILE_SCALE + (TILE_SCALE / 2), height * (location.getPosition().getZ() + 1), -regionY * TILE_SCALE - (TILE_SCALE / 2)); + GL11.glTranslatef(regionX * TILE_SCALE + (TILE_SCALE / 2), height + (location.getPosition().getZ() * 0), -regionY * TILE_SCALE - (TILE_SCALE / 2)); for (int i = 0; i < object.getObjectModels().length; ++i) { @@ -589,60 +634,14 @@ public class ModelViewer drawModel(md, object.getRecolorToFind(), object.getRecolorToReplace()); } - GL11.glTranslatef(-regionX * TILE_SCALE - (TILE_SCALE / 2), -(height * (location.getPosition().getZ() + 1)), regionY * TILE_SCALE + (TILE_SCALE / 2)); + GL11.glTranslatef(-regionX * TILE_SCALE - (TILE_SCALE / 2), -(height + (location.getPosition().getZ() * 0)), regionY * TILE_SCALE + (TILE_SCALE / 2)); GL11.glPopMatrix(); } } - private static void loadUnderlays() throws IOException - { - for (int i = 0; i < NUM_UNDERLAYS; ++i) - { - try (FileInputStream fin = new FileInputStream("underlays/" + i + ".json")) - { - UnderlayDefinition underlay = new Gson().fromJson(new InputStreamReader(fin), UnderlayDefinition.class); - underlays[i] = underlay; - } - catch (FileNotFoundException ex) - { - } - } - } - - private static void loadOverlays() throws IOException - { - for (int i = 0; i < NUM_OVERLAYS; ++i) - { - try (FileInputStream fin = new FileInputStream("overlays/" + i + ".json")) - { - OverlayDefinition overlay = new Gson().fromJson(new InputStreamReader(fin), OverlayDefinition.class); - overlays[i] = overlay; - } - catch (FileNotFoundException ex) - { - } - } - } - private static ObjectDefinition getObject(int id) { - ObjectDefinition object = objects[id]; - if (object != null) - { - return object; - } - - try (FileInputStream fin = new FileInputStream("objects/" + id + ".json")) - { - object = new Gson().fromJson(new InputStreamReader(fin), ObjectDefinition.class); - objects[id] = object; - return object; - } - catch (IOException ex) - { - logger.warn(null, ex); - return null; - } + return objectManager.getObject(id); } private static Texture getTexture(int id) @@ -653,73 +652,54 @@ public class ModelViewer return texture; } - TextureDefinition td; - try (FileInputStream fin = new FileInputStream("textures/" + id + ".json")) + TextureDefinition textureDefinition = textureManager.findTexture(id); + + SpriteDefinition spriteDefinition = spriteManager.findSprite(textureDefinition.getFileIds()[0], 0); + + int width = spriteDefinition.getWidth(); + int height = spriteDefinition.getHeight(); + + int[] rgb = spriteDefinition.getPixels(); + + ByteBuffer buffer = ByteBuffer.allocateDirect(rgb.length * 4); + for (int i = 0; i < rgb.length; ++i) { - td = new Gson().fromJson(new InputStreamReader(fin), TextureDefinition.class); - } - catch (IOException ex) - { - logger.warn(null, ex); - return null; + int pixel = rgb[i]; + + // argb -> rgba + int a = pixel >>> 24; + int r = (pixel >> 16) & 0xff; + int g = (pixel >> 8) & 0xff; + int b = pixel & 0xff; + + buffer.put((byte) r); + buffer.put((byte) g); + buffer.put((byte) b); + buffer.put((byte) a); } + buffer.position(0); - try (FileInputStream fin = new FileInputStream("sprite/" + td.getFileIds()[0] + "-0.png")) - { - BufferedImage image = ImageIO.read(fin); + int glTexture = GL11.glGenTextures(); + GL11.glBindTexture(GL11.GL_TEXTURE_2D, glTexture); - int width = image.getWidth(); - int height = image.getHeight(); - int[] rgb = new int[width * height]; + //Setup filtering, i.e. how OpenGL will interpolate the pixels when scaling up or down + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - int[] out = image.getRGB(0, 0, width, height, rgb, 0, width); - assert rgb == out; + //Setup wrap mode, i.e. how OpenGL will handle pixels outside of the expected range + //Note: GL_CLAMP_TO_EDGE is part of GL12 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - ByteBuffer buffer = ByteBuffer.allocateDirect(rgb.length * 4); - for (int i = 0; i < rgb.length; ++i) - { - int pixel = rgb[i]; + GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, width, height, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer); - // argb -> rgba - int a = pixel >>> 24; - int r = (pixel >> 16) & 0xff; - int g = (pixel >> 8) & 0xff; - int b = pixel & 0xff; + GL11.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); // Linear Filtering + GL11.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); // Linear Filtering - buffer.put((byte) r); - buffer.put((byte) g); - buffer.put((byte) b); - buffer.put((byte) a); - } - buffer.position(0); + texture = new Texture(rgb, width, height, glTexture); + textures.put(id, texture); - int glTexture = GL11.glGenTextures(); - GL11.glBindTexture(GL11.GL_TEXTURE_2D, glTexture); - - //Setup filtering, i.e. how OpenGL will interpolate the pixels when scaling up or down - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - //Setup wrap mode, i.e. how OpenGL will handle pixels outside of the expected range - //Note: GL_CLAMP_TO_EDGE is part of GL12 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, width, height, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer); - - GL11.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); // Linear Filtering - GL11.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); // Linear Filtering - - texture = new Texture(rgb, width, height, glTexture); - textures.put(id, texture); - - return texture; - } - catch (IOException ex) - { - logger.warn(null, ex); - return null; - } + return texture; } // found these two functions here https://www.rune-server.org/runescape-development/rs2-client/tools/589900-rs2-hsb-color-picker.html @@ -729,9 +709,9 @@ public class ModelViewer float hue = (HSB[0]); float saturation = (HSB[1]); float brightness = (HSB[2]); - int encode_hue = (int) (hue * 63); //to 6-bits - int encode_saturation = (int) (saturation * 7); //to 3-bits - int encode_brightness = (int) (brightness * 127); //to 7-bits + int encode_hue = (int) (hue * 63); //to 6-bits + int encode_saturation = (int) (saturation * 7); //to 3-bits + int encode_brightness = (int) (brightness * 127); //to 7-bits return (encode_hue << 10) + (encode_saturation << 7) + (encode_brightness); } diff --git a/model-viewer/src/main/java/net/runelite/modelviewer/Scene.java b/model-viewer/src/main/java/net/runelite/modelviewer/Scene.java new file mode 100644 index 0000000000..8fab7e0b86 --- /dev/null +++ b/model-viewer/src/main/java/net/runelite/modelviewer/Scene.java @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2018, Adam + * 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 lombok.AllArgsConstructor; +import lombok.Getter; +import net.runelite.cache.definitions.OverlayDefinition; +import net.runelite.cache.definitions.UnderlayDefinition; +import net.runelite.cache.definitions.providers.OverlayProvider; +import net.runelite.cache.definitions.providers.UnderlayProvider; +import net.runelite.cache.item.ColorPalette; +import net.runelite.cache.region.Region; + +@AllArgsConstructor +public class Scene +{ + private static final int REGION_SIZE = 64; + private static final int BLEND = 5; + + private static final ColorPalette colorPalette = new ColorPalette(0.9d, 0, 512); + + static + { + assert Region.X == Region.Y; + } + + private final int[] hues = new int[REGION_SIZE]; + private final int[] sats = new int[REGION_SIZE]; + private final int[] light = new int[REGION_SIZE]; + private final int[] mul = new int[REGION_SIZE]; + private final int[] num = new int[REGION_SIZE]; + + private final UnderlayProvider underlayProvider; + private final OverlayProvider overlayProvider; + + @Getter + private final SceneTileModel[][][] sceneTiles = new SceneTileModel[Region.Z][Region.X][Region.Y]; + + @Getter + private final SceneTilePaint[][][] sceneTilePaint = new SceneTilePaint[Region.Z][Region.X][Region.Y]; + + public void loadRegion(Region region) + { + int[][] field3834 = new int[Region.X][Region.Y]; + int var11 = (int) Math.sqrt(5100.0D); + int var63 = var11 * 768 >> 8; + + for (int z = 0; z < Region.Z; ++z) + { + for (int x = 1; x < Region.X - 1; ++x) + { + for (int y = 1; y < Region.Y - 1; ++y) + { + int dx = region.getTileHeight(z, x + 1, y) - region.getTileHeight(z, x - 1, y); + int dy = region.getTileHeight(z, x, y + 1) - region.getTileHeight(z, x, y - 1); + int var17 = (int) Math.sqrt((double) (dx * dx + dy * dy + 65536)); + int var18 = (dx << 8) / var17; + int var50 = 65536 / var17; + int var20 = (dy << 8) / var17; + int var21 = (var20 * -50 + var18 * -50 + var50 * -10) / var63 + 96; +// int var22 = (var68[y - 1][x] >> 2) + (var68[y][x - 1] >> 2) + (var68[y + 1][x] >> 3) + (var68[y][x + 1] >> 3) + (var68[y][x] >> 1); + int var22 = 0; + field3834[y][x] = var21 - var22; + } + } + + for (int i = 0; i < REGION_SIZE; ++i) + { + hues[i] = 0; + sats[i] = 0; + light[i] = 0; + mul[i] = 0; + num[i] = 0; + } + + for (int x = -BLEND; x < Region.X + BLEND; ++x) + { + for (int y = 0; y < Region.Y; ++y) + { + int xr = x + BLEND; + if (xr >= 0 && xr < Region.X) + { + int underlayId = region.getUnderlayId(z, xr, y); + if (underlayId > 0) + { + UnderlayDefinition underlay = underlayProvider.provide(underlayId - 1); + hues[y] += underlay.getHue(); + sats[y] += underlay.getSaturation(); + light[y] += underlay.getLightness(); + mul[y] += underlay.getHueMultiplier(); + num[y]++; + } + } + + int xl = x - BLEND; + if (xl >= 0 && xl < Region.X) + { + int underlayId = region.getUnderlayId(z, xl, y); + if (underlayId > 0) + { + UnderlayDefinition underlay = underlayProvider.provide(underlayId - 1); + hues[y] -= underlay.getHue(); + sats[y] -= underlay.getSaturation(); + light[y] -= underlay.getLightness(); + mul[y] -= underlay.getHueMultiplier(); + num[y]--; + } + } + } + + if (x >= 1 && x < Region.X - 1) + { + int runningHues = 0; + int runningSat = 0; + int runningLight = 0; + int runningMultiplier = 0; + int runningNumber = 0; + + for (int y = -BLEND; y < Region.Y + BLEND; ++y) + { + int yu = y + BLEND; + if (yu >= 0 && yu < Region.Y) + { + runningHues += hues[yu]; + runningSat += sats[yu]; + runningLight += light[yu]; + runningMultiplier += mul[yu]; + runningNumber += num[yu]; + } + + int yd = y - BLEND; + if (yd >= 0 && yd < Region.Y) + { + runningHues -= hues[yd]; + runningSat -= sats[yd]; + runningLight -= light[yd]; + runningMultiplier -= mul[yd]; + runningNumber -= num[yd]; + } + + if (y >= 1 && y < Region.Y - 1) + { + int underlayId = region.getUnderlayId(z, x, y); + int overlayId = region.getOverlayId(z, x, y); + + if (underlayId > 0 || overlayId > 0) + { + int tileHeight = region.getTileHeight(z, x, y); + int tileHeightX1 = region.getTileHeight(z, x + 1, y); + int tileHeightX1Y1 = region.getTileHeight(z, x + 1, y + 1); + int tileHeightY1 = region.getTileHeight(z, x, y + 1); + + int m1 = field3834[x][y]; + int m2 = field3834[x + 1][y]; + int m3 = field3834[x + 1][y + 1]; + int m4 = field3834[x][y + 1]; + + int underlayHsl = -1; + if (underlayId > 0) + { + int avgHue = runningHues * 256 / runningMultiplier; + int avgSat = runningSat / runningNumber; + int avgLight = runningLight / runningNumber; + + underlayHsl = packHsl(avgHue, avgSat, avgLight); + } + + int underlayColor = 0; + if (underlayHsl != -1) + { + underlayColor = colorPalette.getColorPalette()[method2115(underlayHsl, 96)]; + } + + if (overlayId == 0) + { + addTile(z, x, y, 0, 0, -1, + tileHeight, tileHeightX1, tileHeightX1Y1, tileHeightY1, + method2115(underlayHsl, m1), method2115(underlayHsl, m2), method2115(underlayHsl, m3), method2115(underlayHsl, m4), + 0, 0, 0, 0, + underlayColor, 0); + } + else + { + int shape = region.getOverlayPath(z, x, y) + 1; + int rotation = region.getOverlayRotation(z, x, y); + OverlayDefinition overlay = overlayProvider.provide(overlayId - 1); + int textureId = overlay.getTexture(); + int overlayHsl; + if (textureId >= 0) + { + overlayHsl = -2; + } + else if (overlay.getRgbColor() == 0xFF_00FF) + { + overlayHsl = -2; + textureId = -1; + } + else + { + int hue = overlay.getHue(); + int sat = overlay.getSaturation(); + int light = overlay.getLightness(); + overlayHsl = packHsl(hue, sat, light); + } + int overlayColor = 0; + if (overlayHsl != -2) + { + int var0 = adjustHSLListness0(overlayHsl, 96); + overlayColor = colorPalette.getColorPalette()[var0]; + } + + if (overlay.getSecondaryRgbColor() != -1) + { + int hue = overlay.getOtherHue(); + int sat = overlay.getOtherSaturation(); + int olight = overlay.getOtherLightness(); + int hsl = packHsl(hue, sat, olight); + int var0 = adjustHSLListness0(hsl, 96); + overlayColor = colorPalette.getColorPalette()[var0]; + } + + addTile(z, x, y, shape, rotation, textureId, + tileHeight, tileHeightX1, tileHeightX1Y1, tileHeightY1, + method2115(underlayHsl, m1), method2115(underlayHsl, m2), method2115(underlayHsl, m3), method2115(underlayHsl, m4), + adjustHSLListness0(overlayHsl, m1), adjustHSLListness0(overlayHsl, m2), adjustHSLListness0(overlayHsl, m3), adjustHSLListness0(overlayHsl, m4), + underlayColor, overlayColor); + } + } + } + } + } + } + } + } + + private void addTile(int z, int x, int y, int shape, int overlayRot, int texture, + int tileHeight, int tileHeightX1, int tileHeightX1Y1, int tileHeightY1, + int underlayColor, int underlayColorX1, int underlayColorX1Y1, int underlayColorY1, + int overlayColor, int overlayColorX1, int overlayColorX1Y1, int overlayColorY1, + int underlayColorRgb, int overlayColorRgb) // for the map + { + if (shape == 0) + { + SceneTilePaint sceneTilePaint = new SceneTilePaint(underlayColor, texture); + this.sceneTilePaint[z][x][y] = sceneTilePaint; + } + else if (shape == 1) + { + SceneTilePaint sceneTilePaint = new SceneTilePaint(overlayColor, texture); + this.sceneTilePaint[z][x][y] = sceneTilePaint; + } + else + { + SceneTileModel sceneTileModel = new SceneTileModel(shape, overlayRot, texture, x, y, + tileHeight, tileHeightX1, tileHeightX1Y1, tileHeightY1, + underlayColor, underlayColorX1, underlayColorX1Y1, underlayColorY1, + overlayColor, overlayColorX1, overlayColorX1Y1, overlayColorY1, + underlayColorRgb, overlayColorRgb); + sceneTiles[z][x][y] = sceneTileModel; + } + } + + private static int packHsl(int h, int s, int l) + { + if (l > 179) + { + s /= 2; + } + + if (l > 192) + { + s /= 2; + } + + if (l > 217) + { + s /= 2; + } + + if (l > 243) + { + s /= 2; + } + + int hsl = (s / 32 << 7) + (h / 4 << 10) + l / 2; + return hsl; + } + + private static int method2115(int hsl, int var1) + { + if (hsl == -1) + { + return 12345678; + } + else + { + var1 = (hsl & 127) * var1 / 128; + if (var1 < 2) + { + var1 = 2; + } + else if (var1 > 126) + { + var1 = 126; + } + + return (hsl & 65408) + var1; + } + } + + static final int adjustHSLListness0(int var0, int var1) + { + if (var0 == -2) + { + return 12345678; + } + else if (var0 == -1) + { + if (var1 < 2) + { + var1 = 2; + } + else if (var1 > 126) + { + var1 = 126; + } + + return var1; + } + else + { + var1 = (var0 & 127) * var1 / 128; + if (var1 < 2) + { + var1 = 2; + } + else if (var1 > 126) + { + var1 = 126; + } + + return (var0 & 65408) + var1; + } + } +} diff --git a/model-viewer/src/main/java/net/runelite/modelviewer/SceneTileModel.java b/model-viewer/src/main/java/net/runelite/modelviewer/SceneTileModel.java new file mode 100644 index 0000000000..77c8885100 --- /dev/null +++ b/model-viewer/src/main/java/net/runelite/modelviewer/SceneTileModel.java @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2018, Adam + * 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 lombok.Getter; + +@Getter +public class SceneTileModel +{ + private static final int[][] TILE_VERTICES; + private static final int[][] TILE_FACES; + + private static final int TILE_SIZE = 128; + private static final int HALF_TILE_SIZE = TILE_SIZE / 2; + private static final int QUARTER_TILE_SIZE = TILE_SIZE / 4; + private static final int THREE_QUARTER_TILE_SIZE = TILE_SIZE * 3 / 4; + + final int[] vertexX; + final int[] vertexY; + final int[] vertexZ; + + private final int[] var26; + private final int[] var27; + + final int[] faceX; + final int[] faceY; + final int[] faceZ; + + final int[] triangleColorA; + final int[] triangleColorB; + final int[] triangleColorC; + + int[] triangleTextureId; + + static + { + + TILE_VERTICES = new int[][]{{1, 3, 5, 7}, {1, 3, 5, 7}, {1, 3, 5, 7}, {1, 3, 5, 7, 6}, {1, 3, 5, 7, 6}, {1, 3, 5, 7, 6}, {1, 3, 5, 7, 6}, {1, 3, 5, 7, 2, 6}, {1, 3, 5, 7, 2, 8}, {1, 3, 5, 7, 2, 8}, {1, 3, 5, 7, 11, 12}, {1, 3, 5, 7, 11, 12}, {1, 3, 5, 7, 13, 14}}; + TILE_FACES = new int[][]{{0, 1, 2, 3, 0, 0, 1, 3}, {1, 1, 2, 3, 1, 0, 1, 3}, {0, 1, 2, 3, 1, 0, 1, 3}, {0, 0, 1, 2, 0, 0, 2, 4, 1, 0, 4, 3}, {0, 0, 1, 4, 0, 0, 4, 3, 1, 1, 2, 4}, {0, 0, 4, 3, 1, 0, 1, 2, 1, 0, 2, 4}, {0, 1, 2, 4, 1, 0, 1, 4, 1, 0, 4, 3}, {0, 4, 1, 2, 0, 4, 2, 5, 1, 0, 4, 5, 1, 0, 5, 3}, {0, 4, 1, 2, 0, 4, 2, 3, 0, 4, 3, 5, 1, 0, 4, 5}, {0, 0, 4, 5, 1, 4, 1, 2, 1, 4, 2, 3, 1, 4, 3, 5}, {0, 0, 1, 5, 0, 1, 4, 5, 0, 1, 2, 4, 1, 0, 5, 3, 1, 5, 4, 3, 1, 4, 2, 3}, {1, 0, 1, 5, 1, 1, 4, 5, 1, 1, 2, 4, 0, 0, 5, 3, 0, 5, 4, 3, 0, 4, 2, 3}, {1, 0, 5, 4, 1, 0, 1, 5, 0, 0, 4, 3, 0, 4, 5, 3, 0, 5, 2, 3, 0, 1, 2, 5}}; + } + + public SceneTileModel(int shape, int overlayRott, int texture, int x, int y, + int tileHeight, int tileHeightX1, int tileHeightX1Y1, int tileHeightY1, + int var10, int var11, int var12, int var13, + int var14, int var15, int var16, int var17, + int var18, int var19) + { + final int[] vertexInfo = TILE_VERTICES[shape]; + final int vertexInfoLength = vertexInfo.length; + + vertexX = new int[vertexInfoLength]; + vertexY = new int[vertexInfoLength]; + vertexZ = new int[vertexInfoLength]; + var26 = new int[vertexInfoLength]; + var27 = new int[vertexInfoLength]; + + final int tileBaseX = x * TILE_SIZE; + final int tileBaseY = y * TILE_SIZE; + + for (int idx = 0; idx < vertexInfoLength; ++idx) + { + int curInfo = vertexInfo[idx]; + if ((curInfo & 1) == 0 && curInfo <= 8) + { + curInfo = (curInfo - overlayRott - overlayRott - 1 & 7) + 1; + } + + if (curInfo > 8 && curInfo <= 12) + { + curInfo = (curInfo - 9 - overlayRott & 3) + 9; + } + + if (curInfo > 12 && curInfo <= 16) + { + curInfo = (curInfo - 13 - overlayRott & 3) + 13; + } + + int vertexX, vertexY, vertexZ; + int var35, var36; + + if (curInfo == 1) + { + vertexX = tileBaseX; + vertexZ = tileBaseY; + vertexY = tileHeight; + var35 = var10; + var36 = var14; + } + else if (curInfo == 2) + { + vertexX = tileBaseX + HALF_TILE_SIZE; + vertexZ = tileBaseY; + vertexY = tileHeightX1 + tileHeight >> 1; + var35 = var11 + var10 >> 1; + var36 = var15 + var14 >> 1; + } + else if (curInfo == 3) + { + vertexX = tileBaseX + TILE_SIZE; + vertexZ = tileBaseY; + vertexY = tileHeightX1; + var35 = var11; + var36 = var15; + } + else if (curInfo == 4) + { + vertexX = tileBaseX + TILE_SIZE; + vertexZ = tileBaseY + HALF_TILE_SIZE; + vertexY = tileHeightX1Y1 + tileHeightX1 >> 1; + var35 = var11 + var12 >> 1; + var36 = var15 + var16 >> 1; + } + else if (curInfo == 5) + { + vertexX = tileBaseX + TILE_SIZE; + vertexZ = tileBaseY + TILE_SIZE; + vertexY = tileHeightX1Y1; + var35 = var12; + var36 = var16; + } + else if (curInfo == 6) + { + vertexX = tileBaseX + HALF_TILE_SIZE; + vertexZ = tileBaseY + TILE_SIZE; + vertexY = tileHeightX1Y1 + tileHeightY1 >> 1; + var35 = var13 + var12 >> 1; + var36 = var17 + var16 >> 1; + } + else if (curInfo == 7) + { + vertexX = tileBaseX; + vertexZ = tileBaseY + TILE_SIZE; + vertexY = tileHeightY1; + var35 = var13; + var36 = var17; + } + else if (curInfo == 8) + { + vertexX = tileBaseX; + vertexZ = tileBaseY + HALF_TILE_SIZE; + vertexY = tileHeightY1 + tileHeight >> 1; + var35 = var13 + var10 >> 1; + var36 = var17 + var14 >> 1; + } + else if (curInfo == 9) + { + vertexX = tileBaseX + HALF_TILE_SIZE; + vertexZ = tileBaseY + QUARTER_TILE_SIZE; + vertexY = tileHeightX1 + tileHeight >> 1; + var35 = var11 + var10 >> 1; + var36 = var15 + var14 >> 1; + } + else if (curInfo == 10) + { + vertexX = tileBaseX + THREE_QUARTER_TILE_SIZE; + vertexZ = tileBaseY + HALF_TILE_SIZE; + vertexY = tileHeightX1Y1 + tileHeightX1 >> 1; + var35 = var11 + var12 >> 1; + var36 = var15 + var16 >> 1; + } + else if (curInfo == 11) + { + vertexX = tileBaseX + HALF_TILE_SIZE; + vertexZ = tileBaseY + THREE_QUARTER_TILE_SIZE; + vertexY = tileHeightX1Y1 + tileHeightY1 >> 1; + var35 = var13 + var12 >> 1; + var36 = var17 + var16 >> 1; + } + else if (curInfo == 12) + { + vertexX = tileBaseX + QUARTER_TILE_SIZE; + vertexZ = tileBaseY + HALF_TILE_SIZE; + vertexY = tileHeightY1 + tileHeight >> 1; + var35 = var13 + var10 >> 1; + var36 = var17 + var14 >> 1; + } + else if (curInfo == 13) + { + vertexX = tileBaseX + QUARTER_TILE_SIZE; + vertexZ = tileBaseY + QUARTER_TILE_SIZE; + vertexY = tileHeight; + var35 = var10; + var36 = var14; + } + else if (curInfo == 14) + { + vertexX = tileBaseX + THREE_QUARTER_TILE_SIZE; + vertexZ = tileBaseY + QUARTER_TILE_SIZE; + vertexY = tileHeightX1; + var35 = var11; + var36 = var15; + } + else if (curInfo == 15) + { + vertexX = tileBaseX + THREE_QUARTER_TILE_SIZE; + vertexZ = tileBaseY + THREE_QUARTER_TILE_SIZE; + vertexY = tileHeightX1Y1; + var35 = var12; + var36 = var16; + } + else + { + vertexX = tileBaseX + QUARTER_TILE_SIZE; + vertexZ = tileBaseY + THREE_QUARTER_TILE_SIZE; + vertexY = tileHeightY1; + var35 = var13; + var36 = var17; + } + + this.vertexX[idx] = vertexX; + this.vertexY[idx] = vertexY; + this.vertexZ[idx] = vertexZ; + var26[idx] = var35; + var27[idx] = var36; + } + + final int[] faceInfo = TILE_FACES[shape]; + final int faceInfoLength = faceInfo.length / 4; + + faceX = new int[faceInfoLength]; + faceY = new int[faceInfoLength]; + faceZ = new int[faceInfoLength]; + + triangleColorA = new int[faceInfoLength]; + triangleColorB = new int[faceInfoLength]; + triangleColorC = new int[faceInfoLength]; + + if (texture != -1) + { + triangleTextureId = new int[faceInfoLength]; + } + + int offset = 0; + for (int idx = 0; idx < faceInfoLength; ++idx) + { + int var = faceInfo[offset]; + int faceX = faceInfo[offset + 1]; + int faceY = faceInfo[offset + 2]; + int faceZ = faceInfo[offset + 3]; + offset += 4; + + if (faceX < 4) + { + faceX = faceX - overlayRott & 3; + } + + if (faceY < 4) + { + faceY = faceY - overlayRott & 3; + } + + if (faceZ < 4) + { + faceZ = faceZ - overlayRott & 3; + } + + this.faceX[idx] = faceX; + this.faceY[idx] = faceY; + this.faceZ[idx] = faceZ; + + if (var == 0) + { + this.triangleColorA[idx] = var26[faceX]; + this.triangleColorB[idx] = var26[faceY]; + this.triangleColorC[idx] = var26[faceZ]; + if (this.triangleTextureId != null) + { + this.triangleTextureId[idx] = -1; + } + } + else + { + this.triangleColorA[idx] = var27[faceX]; + this.triangleColorB[idx] = var27[faceY]; + this.triangleColorC[idx] = var27[faceZ]; + if (this.triangleTextureId != null) + { + this.triangleTextureId[idx] = texture; + } + } + } + } +} diff --git a/model-viewer/src/main/java/net/runelite/modelviewer/SceneTilePaint.java b/model-viewer/src/main/java/net/runelite/modelviewer/SceneTilePaint.java new file mode 100644 index 0000000000..616479f274 --- /dev/null +++ b/model-viewer/src/main/java/net/runelite/modelviewer/SceneTilePaint.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018, Adam + * 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 lombok.AllArgsConstructor; + +@AllArgsConstructor +public class SceneTilePaint +{ + final int color; + final int texture; +} \ No newline at end of file