Thread: Rendering models to website with THREE.js

Results 1 to 10 of 10
  1. #1 Rendering models to website with THREE.js 
    *breaks walking*

    Cody_'s Avatar
    Join Date
    Dec 2010
    Posts
    721
    Thanks given
    204
    Thanks received
    189
    Discord
    View profile
    Rep Power
    267
    Worked on this over the past couple days, still working on it a bit.

    Preview:


    Still missing a decent bit, haven't really touched textures, particles, etc. Will update as I go along. Hoping to get a full render by the time I'm done.

    Lemme know if I forgot to copy/paste anything here.
    Not looking to make a full tutorial, just some references for anyone who needs.

    Pass an rsmesh to the below javascript file in JSON format, should do the rest.

    Code below should give an idea on how you can render individual items, head models, full body models, etc

    Code:
    let renderer;
    let scene;
    let camera;
    
    let cube;
    
    let controls;
    
    function loadScene(model) {
        console.log(model);
        scene = new THREE.Scene();
    
        let width = 250;
        let height = 400;
    
        camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 6000);
    
        renderer = new THREE.WebGLRenderer();
        renderer.setSize(width, height);
    
        $('#model-viewer').append(renderer.domElement);
    
        //ADD CUBE
        let vertices = [];
    
        let hasAlpha = model.FaceAlphas != null;
        let hasFaceTypes = model.FaceType != null;
    
        //BUILD GEOMETRY
        for (let i = 0; i < model.FaceCount; i++) {
    
            let alpha = hasAlpha ? model.FaceAlphas[i] : 0;
            if (alpha == -1) continue;
    
            alpha = ~alpha & 0xFF;
            let faceType = hasFaceTypes ? model.FaceType[i] & 0x3 : 0;
    
            let faceA, faceB, faceC;
            switch (faceType) {
                case 0:
                case 1:
                    faceA = model.TriangleX[i];
                    faceB = model.TriangleY[i];
                    faceC = model.TriangleZ[i];
                    break;
                case 2:
                case 3:
                    faceA = model.TexTriX[i];
                    faceB = model.TexTriY[i];
                    faceC = model.TexTriZ[i];
                    break;
                default:
                    throw new Error('Unknown face type=' + faceType);
            }
    
            let textureId = model.FaceTextures == null ? -1 : model.FaceTextures[i];
    
            let u, v;
            let colour = model.RealFaceColour[i];
            let r = (colour >> 16) & 0xFF;
            let g = (colour >> 8) & 0xFF;
            let b = colour & 0xFF;
            vertices.push({ pos: [model.VertexX[faceA], model.VertexY[faceA], model.VertexZ[faceA]], norm: [faceA, faceB, faceC], colors: [r, g, b, alpha] });
            vertices.push({ pos: [model.VertexX[faceB], model.VertexY[faceB], model.VertexZ[faceB]], norm: [faceA, faceB, faceC], colors: [r, g, b, alpha] });
            vertices.push({ pos: [model.VertexX[faceC], model.VertexY[faceC], model.VertexZ[faceC]], norm: [faceA, faceB, faceC], colors: [r, g, b, alpha] });
        }
    
        let positions = [];
        let normals = [];
        let colors = [];
        for (let vertex of vertices) {
            positions.push(...vertex.pos);
            normals.push(...vertex.norm);
            colors.push(...vertex.colors);
        }
    
        let geometry = new THREE.BufferGeometry();
        geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(positions), 3));
        geometry.setAttribute('normal', new THREE.BufferAttribute(new Float32Array(normals), 3));
        geometry.addAttribute('color', new THREE.BufferAttribute(new Uint8Array(colors), 4, true));
    
        geometry.normalizeNormals();
        geometry.computeVertexNormals();
    
    
        let material = new THREE.MeshBasicMaterial({ vertexColors: THREE.VertexColors });
        cube = new THREE.Mesh(geometry, material);
    
        cube.rotation.x = Math.PI; //model renders upside down for some reason
    
        scene.add(cube);
        camera.position.z = 3000;
    
        controls = new THREE.TrackballControls(camera, renderer.domElement);
        controls.target.set(0, 500, 0);
    
        controls.addEventListener('end', function() {
    
        });
    
        controls.noPan = true;
        controls.rotateSpeed = 0.03;
    
        animate();
    }
    
    function animate() {
        requestAnimationFrame(animate);
    
        controls.update();
    
        renderer.render(scene, camera);
    }
    Code:
        public static RSMesh renderPlayerHead(Account account) {
            try {
                int[] defaultLook = getDefaultLook();
                RSMesh[] meshes = new RSMesh[15];
                int size = 0;
                int[] equipped = account.getEquippedItems();
                if (equipped == null) {
                    equipped = new int[15];
                    Arrays.fill(equipped, -1);
                }
                if(equipped[EquipmentDefaults.HAT] != -1) {
                    ItemDefinitions defs = ItemDefinitions.getItemDefinitions(equipped[EquipmentDefaults.HAT]);
                    RSMesh mesh;
                    if(defs != null && (mesh = defs.getHeadMesh(account.getGender() == 1, null)) != null)
                        meshes[size++] = mesh;
                }
                for (int look : defaultLook) {
                    if (look == -1) continue;
                    IdentiKitDefinition defs = IdentiKitDefinition.getIdentikitDefinition(look);
                    RSMesh mesh;
                    if (defs == null || (mesh = defs.renderHead(size > 0)) == null) continue;
                    meshes[size++] = mesh;
                }
                return new RSMesh(meshes, size);
            } catch(Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        public static RSMesh renderPlayerBody(Account account) {
            try {
                int[] look = getDefaultLook();
                LinkedTreeMap<String, Object>[] equipped = account.getEquippedItems();
                if (equipped == null)
                    equipped = new LinkedTreeMap[15];
                RSMesh[] meshes = new RSMesh[15];
                int size = 0;
                for(int i = 0; i < 4; i++) {
                    if(equipped[i] == null) continue;
                    int id = (int) ((double) equipped[i].get("id"));
                    if(id == -1) continue;
                    MeshModifier modifier = null;
                    if(equipped[i].containsKey("colours")) {
                        short[] colours = new short[4];
                        ArrayList<Double> iColours = (ArrayList<Double>) equipped[i].get("colours");
                        int index = 0;
                        for(Double col : iColours)
                            colours[index++] = col.shortValue();
                        modifier = new MeshModifier(colours, null);
                    }
                    ItemDefinitions defs = ItemDefinitions.getItemDefinitions(id);
                    RSMesh mesh;
                    if (defs == null || (mesh = defs.getBodyMesh(account.getGender() == 1, modifier)) == null) continue;
                    meshes[size++] = mesh;
                }
                //chest
                RSMesh mesh;
                int id = (int) ((double) equipped[EquipmentDefaults.CHEST].get("id"));
                if(id == -1)
                    mesh = renderLook(2);
                else
                    mesh = renderItem(account, id, null);
                if(mesh != null)
                    meshes[size++] = mesh;
    
                id = (int) ((double) equipped[EquipmentDefaults.SHIELD].get("id"));
                if(id != -1)
                    meshes[size++] = renderItem(account, id, null);
    
                id = (int) ((double) equipped[EquipmentDefaults.CHEST].get("id"));
                mesh = null;
                if(look[3] == -1 && (id == -1 || !EquipmentDefaults.hideArms(id)))
                    mesh = renderLook(3);
                else if(id != -1 && !EquipmentDefaults.hideArms(id))
                    mesh = renderIdentikit(account.getGender() == 0 ? 26 : 61);
                if(mesh != null)
                    meshes[size++] = mesh;
    
                id = (int) ((double) equipped[EquipmentDefaults.LEGS].get("id"));
                if(id == -1)
                    mesh = renderLook(5);
                else
                    mesh = renderItem(account, id, null);
                if(mesh != null)
                    meshes[size++] = mesh;
    
                id = (int) ((double) equipped[EquipmentDefaults.HAT].get("id"));
                mesh = null;
                if(look[0] != -1 && (id == -1 || !EquipmentDefaults.hideHair(id))) {
                    if(id == -1)
                        mesh = renderLook(0);
                    else {
                        ItemDefinitions defs = ItemDefinitions.getItemDefinitions(id);
                        if(defs != null) {
                            int style = EquipmentDefaults.getHatHairStyle(getDefaultLook()[0], defs.faceMask(), account.getGender() == 1);
                            if (style != -1)
                                mesh = renderIdentikit(style);
                        }
                    }
                }
                if(mesh != null)
                    meshes[size++] = mesh;
    
                id = (int) ((double) equipped[EquipmentDefaults.HANDS].get("id"));
                if(id == -1)
                    mesh = renderLook(4);
                else
                    mesh = renderItem(account, id, null);
                meshes[size++] = mesh;
    
                id = (int) ((double) equipped[EquipmentDefaults.FEET].get("id"));
                if(id == -1)
                    mesh = renderLook(6);
                else
                    mesh = renderItem(account, id, null);
                meshes[size++] = mesh;
    
                boolean male = account.getGender() == 0;
                int slot = male ? EquipmentDefaults.HAT : EquipmentDefaults.CHEST;
                id = (int) ((double) equipped[slot].get("id"));
                if(male && look[1] != -1 && (id == -1 || (male && !EquipmentDefaults.hideBeard(id))))
                    meshes[size++] = renderLook(1);
    
                return new RSMesh(meshes, size);
            } catch(Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        public static RSMesh renderLook(int look) {
            int id = getDefaultLook()[look];
            if(id == -1) return null;
            return renderIdentikit(id);
        }
    
        public static RSMesh renderIdentikit(int id) {
            IdentiKitDefinition defs = IdentiKitDefinition.getIdentikitDefinition(id);
            if(defs == null) return null;
            return defs.renderBody();
        }
    
        public static RSMesh renderItem(Account account, int id, MeshModifier modifier) {
            ItemDefinitions defs = ItemDefinitions.getItemDefinitions(id);
            if(defs == null) return null;
            return defs.getBodyMesh(account.getGender() == 1, modifier);
        }
    Code:
    package com.cryo.cache.loaders.model;
    
    import com.cryo.cache.io.InputStream;
    import com.cryo.utils.Utilities;
    
    public class RSMesh {
    
        private int id;
        public int version = 12;
        public int vertexCount;
        public int maxDepth;
        public int faceCount;
        public byte priority;
        public int texturedFaceCount;
        public int[] textureRenderTypes;
        public int[] vertexX;
        public int[] vertexY;
        public int[] vertexZ;
        public short[] triangleX;
        public short[] triangleY;
        public short[] triangleZ;
        public int[] vertexSkins;
        public byte[] faceType;
        public byte[] facePriorities;
        public byte[] faceAlphas;
        public int[] textureSkins;
        public short[] faceTextures;
        public short[] faceColor;
        public int[] realFaceColour;
        public byte[] texturePos;
        public short[] texTriX;
        public short[] texTriY;
        public short[] texTriZ;
        public int[] particleDirectionX;
        public int[] particleDirectionY;
        public int[] particleDirectionZ;
        public int[] particleLifespanX;
        public int[] particleLifespanY;
        public int[] particleLifespanZ;
        public int[] texturePrimaryColor;
        public int[] textureSecondaryColor;
        public short[] aShortArray1980;
        public short[] aShortArray1981;
    
        private ParticleEmitterConfig[] particleConfig;
        private SurfaceSkin[] surfaceSkins;
        private VertexNormal[] isolatedVertexNormals;
    
        public RSMesh() {
            vertexCount = 0;
            faceCount = 0;
            texturedFaceCount = 0;
            int i_3 = 0;
            int i_4 = 0;
            int i_5 = 0;
            boolean bool_6 = false;
            boolean bool_7 = false;
            boolean bool_8 = false;
            boolean bool_9 = false;
            boolean bool_10 = false;
            boolean bool_11 = false;
            priority = -1;
        }
    
        public void decode(byte[] data) {
            if (data[data.length - 1] == -1 && data[data.length - 2] == -1) {
                decodeNewFormat(data);
            } else {
                decodeOldFormat(data);
            }
        }
    
        public void decodeNewFormat(byte[] data) {
            InputStream first = new InputStream(data);
            InputStream second = new InputStream(data);
            InputStream third = new InputStream(data);
            InputStream fourth = new InputStream(data);
            InputStream fifth = new InputStream(data);
            InputStream sixth = new InputStream(data);
            InputStream seventh = new InputStream(data);
            first.setOffset(data.length - 23);
            vertexCount = first.readUnsignedShort();
            faceCount = first.readUnsignedShort();
            texturedFaceCount = first.readUnsignedByte();
            int i_9 = first.readUnsignedByte();
            boolean hasFaceRenderTypes = (i_9 & 0x1) == 1;
            boolean hasParticleEffects = (i_9 & 0x2) == 2;
            boolean hasBillboards = (i_9 & 0x4) == 4;
            boolean hasVersion = (i_9 & 0x8) == 8;
            if (hasVersion) {
                first.setOffset(first.getOffset() - 7);
                version = first.readUnsignedByte();
                first.setOffset(first.getOffset() + 6);
            }
    
            int modelPriority = first.readUnsignedByte();
            int hasFaceAlpha = first.readUnsignedByte();
            int hasFaceSkins = first.readUnsignedByte();
            int hasFaceTextures = first.readUnsignedByte();
            int hasVertexSkins = first.readUnsignedByte();
            int modelVerticesX = first.readUnsignedShort();
            int modelVerticesY = first.readUnsignedShort();
            int modelVerticesZ = first.readUnsignedShort();
            int faceIndices = first.readUnsignedShort();
            int textureIndices = first.readUnsignedShort();
            if(id == 60060)
                System.out.println("face: "+faceIndices+" tex: "+textureIndices);
            int numVertexSkins = 0;
            int i_25 = 0;
            int i_26 = 0;
            if (texturedFaceCount > 0) {
                textureRenderTypes = new int[texturedFaceCount];
                first.setOffset(0);
    
                for (int i = 0; i < texturedFaceCount; i++) {
                    int b_28 = textureRenderTypes[i] = first.readByte();
                    if (b_28 == 0) {
                        ++numVertexSkins;
                    }
    
                    if (b_28 >= 1 && b_28 <= 3) {
                        ++i_25;
                    }
    
                    if (b_28 == 2) {
                        ++i_26;
                    }
                }
            }
    
            int totalFaces = texturedFaceCount;
            int flagBufferOffset = totalFaces;
            totalFaces += vertexCount;
            int i_29 = totalFaces;
            if (hasFaceRenderTypes) {
                totalFaces += faceCount;
            }
    
            int i_30 = totalFaces;
            totalFaces += faceCount;
            int i_31 = totalFaces;
            if (modelPriority == 255) {
                totalFaces += faceCount;
            }
    
            int i_32 = totalFaces;
            if (hasFaceSkins == 1) {
                totalFaces += faceCount;
            }
    
            int vertSkinsBufferOffset = totalFaces;
            if (hasVertexSkins == 1) {
                totalFaces += vertexCount;
            }
    
            int i_34 = totalFaces;
            if (hasFaceAlpha == 1) {
                totalFaces += faceCount;
            }
    
            int i_35 = totalFaces;
            totalFaces += faceIndices;
            int i_36 = totalFaces;
            if (hasFaceTextures == 1) {
                totalFaces += faceCount * 2;
            }
    
            int i_37 = totalFaces;
            totalFaces += textureIndices;
            int i_38 = totalFaces;
            totalFaces += faceCount * 2;
            int vertXBufferOffset = totalFaces;
            totalFaces += modelVerticesX;
            int vertYBufferOffset = totalFaces;
            totalFaces += modelVerticesY;
            int vertZBufferOffset = totalFaces;
            totalFaces += modelVerticesZ;
            int simple_tex_pmn_offset = totalFaces;
            totalFaces += numVertexSkins * 6;
            int i_43 = totalFaces;
            totalFaces += i_25 * 6;
            byte b_44 = 6;
            if (version == 14) {
                b_44 = 7;
            } else if (version >= 15) {
                b_44 = 9;
            }
    
            int i_45 = totalFaces;
            totalFaces += i_25 * b_44;
            int i_46 = totalFaces;
            totalFaces += i_25;
            int i_47 = totalFaces;
            totalFaces += i_25;
            int i_48 = totalFaces;
            totalFaces = i_26 * 2 + totalFaces + i_25;
            vertexX = new int[vertexCount];
            vertexY = new int[vertexCount];
            vertexZ = new int[vertexCount];
            triangleX = new short[faceCount];
            triangleY = new short[faceCount];
            triangleZ = new short[faceCount];
            if (hasVertexSkins == 1) {
                vertexSkins = new int[vertexCount];
            }
    
            if (hasFaceRenderTypes) {
                faceType = new byte[faceCount];
            }
    
            if (modelPriority == 255) {
                facePriorities = new byte[faceCount];
            } else {
                priority = (byte) modelPriority;
            }
    
            if (hasFaceAlpha == 1) {
                faceAlphas = new byte[faceCount];
            }
    
            if (hasFaceSkins == 1) {
                textureSkins = new int[faceCount];
            }
    
            if (hasFaceTextures == 1) {
                faceTextures = new short[faceCount];
            }
    
            if (hasFaceTextures == 1 && texturedFaceCount > 0) {
                texturePos = new byte[faceCount];
            }
    
            faceColor = new short[faceCount];
            if (texturedFaceCount > 0) {
                texTriX = new short[texturedFaceCount];
                texTriY = new short[texturedFaceCount];
                texTriZ = new short[texturedFaceCount];
                if (i_25 > 0) {
                    particleDirectionX = new int[i_25];
                    particleDirectionY = new int[i_25];
                    particleDirectionZ = new int[i_25];
                    particleLifespanX = new int[i_25];
                    particleLifespanY = new int[i_25];
                    particleLifespanZ = new int[i_25];
                }
    
                if (i_26 > 0) {
                    texturePrimaryColor = new int[i_26];
                    textureSecondaryColor = new int[i_26];
                }
            }
    
    
            first.setOffset(flagBufferOffset);
            second.setOffset(vertXBufferOffset);
            third.setOffset(vertYBufferOffset);
            fourth.setOffset(vertZBufferOffset);
            fifth.setOffset(vertSkinsBufferOffset);
            int baseX = 0;
            int baseY = 0;
            int baseZ = 0;
    
            for (int vertex = 0; vertex < vertexCount; vertex++) {
                int offsetFlags = first.readUnsignedByte();
                int vertextOffsetX = 0;
                if ((offsetFlags & 0x1) != 0) {
                    vertextOffsetX = second.readUnsignedSmart2();
                }
    
                int vertextOffsetY = 0;
                if ((offsetFlags & 0x2) != 0) {
                    vertextOffsetY = third.readUnsignedSmart2();
                }
    
                int vertetxOffsetZ = 0;
                if ((offsetFlags & 0x4) != 0) {
                    vertetxOffsetZ = fourth.readUnsignedSmart2();
                }
    
                vertexX[vertex] = baseX + vertextOffsetX;
                vertexY[vertex] = baseY + vertextOffsetY;
                vertexZ[vertex] = baseZ + vertetxOffsetZ;
                baseX = vertexX[vertex];
                baseY = vertexY[vertex];
                baseZ = vertexZ[vertex];
                if (hasVertexSkins == 1) {
                    vertexSkins[vertex] = fifth.readUnsignedByte();
                }
            }
    
            first.setOffset(i_38);
            second.setOffset(i_29);
            third.setOffset(i_31);
            fourth.setOffset(i_34);
            fifth.setOffset(i_32);
            sixth.setOffset(i_36);
            seventh.setOffset(i_37);
    
            for (int i_53 = 0; i_53 < faceCount; i_53++) {
                faceColor[i_53] = (short) first.readUnsignedShort();
                if (hasFaceRenderTypes) {
                    faceType[i_53] = (byte) second.readByte();
                }
    
                if (modelPriority == 255) {
                    facePriorities[i_53] = (byte) third.readByte();
                }
    
                if (hasFaceAlpha == 1) {
                    faceAlphas[i_53] = (byte) fourth.readByte();
                }
    
                if (hasFaceSkins == 1) {
                    textureSkins[i_53] = fifth.readUnsignedByte();
                }
    
                if (hasFaceTextures == 1) {
                    faceTextures[i_53] = (short) (sixth.readUnsignedShort() - 1);
                }
    
                if (texturePos != null) {
                    if (faceTextures[i_53] != -1) {
                        texturePos[i_53] = (byte) (seventh.readUnsignedByte() - 1);
                    } else {
                        texturePos[i_53] = -1;
                    }
                }
            }
    
            maxDepth = -1;
            first.setOffset(i_35);
            second.setOffset(i_30);
            calculateMaxDepth(first, second);
            first.setOffset(simple_tex_pmn_offset);
            second.setOffset(i_43);
            third.setOffset(i_45);
            fourth.setOffset(i_46);
            fifth.setOffset(i_47);
            sixth.setOffset(i_48);
            decodeTexturedTriangles(first, second, third, fourth, fifth, sixth);
            first.setOffset(totalFaces);
            if (hasParticleEffects) {
                int emitterCount = first.readUnsignedByte();
                if (emitterCount > 0) {
                    particleConfig = new ParticleEmitterConfig[emitterCount];
    
                    for (int i = 0; i < emitterCount; i++) {
                        int particleId = first.readUnsignedShort();
                        int faceIdx = first.readUnsignedShort();
                        byte b_60;
                        if (modelPriority == 255) {
                            b_60 = facePriorities[faceIdx];
                        } else {
                            b_60 = (byte) modelPriority;
                        }
    
                        particleConfig[i] = new ParticleEmitterConfig(particleId, triangleX[faceIdx], triangleY[faceIdx], triangleZ[faceIdx], b_60);
                    }
                }
    
                int surfaceSkinCount = first.readUnsignedByte();
                if (surfaceSkinCount > 0) {
                    surfaceSkins = new SurfaceSkin[surfaceSkinCount];
    
                    for (int i = 0; i < surfaceSkinCount; i++) {
                        int x = first.readUnsignedShort();
                        int y = first.readUnsignedShort();
                        surfaceSkins[i] = new SurfaceSkin(x, y);
                    }
                }
            }
    
            if (hasBillboards) {
                int i_53 = first.readUnsignedByte();
                if (i_53 > 0) {
                    isolatedVertexNormals = new VertexNormal[i_53];
    
                    for (int i = 0; i < i_53; i++) {
                        int vertextOffsetX = first.readUnsignedShort();
                        int vertextOffsetY = first.readUnsignedShort();
                        int vertetxOffsetZ = first.readUnsignedByte();
                        byte b_58 = (byte) first.readByte();
                        isolatedVertexNormals[i] = new VertexNormal(vertextOffsetX, vertextOffsetY, vertetxOffsetZ, b_58);
                    }
                }
            }
        }
    
        public void decodeOldFormat(byte[] data) {
            boolean bool_2 = false;
            boolean bool_3 = false;
            InputStream first = new InputStream(data);
            InputStream second = new InputStream(data);
            InputStream third = new InputStream(data);
            InputStream fourth = new InputStream(data);
            InputStream firth = new InputStream(data);
            first.setOffset(data.length - 18);
            vertexCount = first.readUnsignedShort();
            faceCount = first.readUnsignedShort();
            texturedFaceCount = first.readUnsignedByte();
            int i_9 = first.readUnsignedByte();
            int i_10 = first.readUnsignedByte();
            int i_11 = first.readUnsignedByte();
            int i_12 = first.readUnsignedByte();
            int i_13 = first.readUnsignedByte();
            int i_14 = first.readUnsignedShort();
            int i_15 = first.readUnsignedShort();
            int i_16 = first.readUnsignedShort();
            int i_17 = first.readUnsignedShort();
            byte b_18 = 0;
            int i_42 = b_18 + vertexCount;
            int i_20 = i_42;
            i_42 += faceCount;
            int i_21 = i_42;
            if (i_10 == 255) {
                i_42 += faceCount;
            }
    
            int i_22 = i_42;
            if (i_12 == 1) {
                i_42 += faceCount;
            }
    
            int i_23 = i_42;
            if (i_9 == 1) {
                i_42 += faceCount;
            }
    
            int i_24 = i_42;
            if (i_13 == 1) {
                i_42 += vertexCount;
            }
    
            int i_25 = i_42;
            if (i_11 == 1) {
                i_42 += faceCount;
            }
    
            int i_26 = i_42;
            i_42 += i_17;
            int i_27 = i_42;
            i_42 += faceCount * 2;
            int i_28 = i_42;
            i_42 += texturedFaceCount * 6;
            int i_29 = i_42;
            i_42 += i_14;
            int i_30 = i_42;
            i_42 += i_15;
            int i_10000 = i_42 + i_16;
            vertexX = new int[vertexCount];
            vertexY = new int[vertexCount];
            vertexZ = new int[vertexCount];
            triangleX = new short[faceCount];
            triangleY = new short[faceCount];
            triangleZ = new short[faceCount];
            if (texturedFaceCount > 0) {
                textureRenderTypes = new int[texturedFaceCount];
                texTriX = new short[texturedFaceCount];
                texTriY = new short[texturedFaceCount];
                texTriZ = new short[texturedFaceCount];
            }
    
            if (i_13 == 1) {
                vertexSkins = new int[vertexCount];
            }
    
            if (i_9 == 1) {
                faceType = new byte[faceCount];
                texturePos = new byte[faceCount];
                faceTextures = new short[faceCount];
            }
    
            if (i_10 == 255) {
                facePriorities = new byte[faceCount];
            } else {
                priority = (byte) i_10;
            }
    
            if (i_11 == 1) {
                faceAlphas = new byte[faceCount];
            }
    
            if (i_12 == 1) {
                textureSkins = new int[faceCount];
            }
    
            faceColor = new short[faceCount];
            first.setOffset(b_18);
            second.setOffset(i_29);
            third.setOffset(i_30);
            fourth.setOffset(i_42);
            firth.setOffset(i_24);
            int i_32 = 0;
            int i_33 = 0;
            int i_34 = 0;
    
            int i_35;
            int i_36;
            int i_39;
            for (i_35 = 0; i_35 < vertexCount; i_35++) {
                i_36 = first.readUnsignedByte();
                int i_37 = 0;
                if ((i_36 & 0x1) != 0) {
                    i_37 = second.readUnsignedSmart2();
                }
    
                int i_38 = 0;
                if ((i_36 & 0x2) != 0) {
                    i_38 = third.readUnsignedSmart2();
                }
    
                i_39 = 0;
                if ((i_36 & 0x4) != 0) {
                    i_39 = fourth.readUnsignedSmart2();
                }
    
                vertexX[i_35] = i_32 + i_37;
                vertexY[i_35] = i_33 + i_38;
                vertexZ[i_35] = i_34 + i_39;
                i_32 = vertexX[i_35];
                i_33 = vertexY[i_35];
                i_34 = vertexZ[i_35];
                if (i_13 == 1) {
                    vertexSkins[i_35] = firth.readUnsignedByte();
                }
            }
    
            first.setOffset(i_27);
            second.setOffset(i_23);
            third.setOffset(i_21);
            fourth.setOffset(i_25);
            firth.setOffset(i_22);
    
            for (i_35 = 0; i_35 < faceCount; i_35++) {
                faceColor[i_35] = (short) first.readUnsignedShort();
                if (i_9 == 1) {
                    i_36 = second.readUnsignedByte();
                    if ((i_36 & 0x1) == 1) {
                        faceType[i_35] = 1;
                        bool_2 = true;
                    } else {
                        faceType[i_35] = 0;
                    }
    
                    if ((i_36 & 0x2) == 2) {
                        texturePos[i_35] = (byte) (i_36 >> 2);
                        faceTextures[i_35] = faceColor[i_35];
                        faceColor[i_35] = 127;
                        if (faceTextures[i_35] != -1) {
                            bool_3 = true;
                        }
                    } else {
                        texturePos[i_35] = -1;
                        faceTextures[i_35] = -1;
                    }
                }
    
                if (i_10 == 255) {
                    facePriorities[i_35] = (byte) third.readByte();
                }
    
                if (i_11 == 1) {
                    faceAlphas[i_35] = (byte) fourth.readByte();
                }
    
                if (i_12 == 1) {
                    textureSkins[i_35] = firth.readUnsignedByte();
                }
            }
    
            maxDepth = -1;
            first.setOffset(i_26);
            second.setOffset(i_20);
            short s_43 = 0;
            short s_44 = 0;
            short s_45 = 0;
            short s_46 = 0;
    
            int i_40;
            for (i_39 = 0; i_39 < faceCount; i_39++) {
                i_40 = second.readUnsignedByte();
                if (i_40 == 1) {
                    s_43 = (short) (first.readUnsignedSmart2() + s_46);
                    s_44 = (short) (first.readUnsignedSmart2() + s_43);
                    s_45 = (short) (first.readUnsignedSmart2() + s_44);
                    s_46 = s_45;
                    triangleX[i_39] = s_43;
                    triangleY[i_39] = s_44;
                    triangleZ[i_39] = s_45;
                    if (s_43 > maxDepth) {
                        maxDepth = s_43;
                    }
    
                    if (s_44 > maxDepth) {
                        maxDepth = s_44;
                    }
    
                    if (s_45 > maxDepth) {
                        maxDepth = s_45;
                    }
                }
    
                if (i_40 == 2) {
                    s_44 = s_45;
                    s_45 = (short) (first.readUnsignedSmart2() + s_46);
                    s_46 = s_45;
                    triangleX[i_39] = s_43;
                    triangleY[i_39] = s_44;
                    triangleZ[i_39] = s_45;
                    if (s_45 > maxDepth) {
                        maxDepth = s_45;
                    }
                }
    
                if (i_40 == 3) {
                    s_43 = s_45;
                    s_45 = (short) (first.readUnsignedSmart2() + s_46);
                    s_46 = s_45;
                    triangleX[i_39] = s_43;
                    triangleY[i_39] = s_44;
                    triangleZ[i_39] = s_45;
                    if (s_45 > maxDepth) {
                        maxDepth = s_45;
                    }
                }
    
                if (i_40 == 4) {
                    short s_41 = s_43;
                    s_43 = s_44;
                    s_44 = s_41;
                    s_45 = (short) (first.readUnsignedSmart2() + s_46);
                    s_46 = s_45;
                    triangleX[i_39] = s_43;
                    triangleY[i_39] = s_41;
                    triangleZ[i_39] = s_45;
                    if (s_45 > maxDepth) {
                        maxDepth = s_45;
                    }
                }
            }
    
            ++maxDepth;
            first.setOffset(i_28);
    
            for (i_39 = 0; i_39 < texturedFaceCount; i_39++) {
                textureRenderTypes[i_39] = 0;
                texTriX[i_39] = (short) first.readUnsignedShort();
                texTriY[i_39] = (short) first.readUnsignedShort();
                texTriZ[i_39] = (short) first.readUnsignedShort();
            }
    
            if (texturePos != null) {
                boolean bool_47 = false;
    
                for (i_40 = 0; i_40 < faceCount; i_40++) {
                    int i_48 = texturePos[i_40] & 0xff;
                    if (i_48 != 255) {
                        if (triangleX[i_40] == (texTriX[i_48] & 0xffff) && triangleY[i_40] == (texTriY[i_48] & 0xffff) && triangleZ[i_40] == (texTriZ[i_48] & 0xffff)) {
                            texturePos[i_40] = -1;
                        } else {
                            bool_47 = true;
                        }
                    }
                }
    
                if (!bool_47) {
                    texturePos = null;
                }
            }
    
            if (!bool_3) {
                faceTextures = null;
            }
    
            if (!bool_2) {
                faceType = null;
            }
        }
    
        public void setRealColours() {
            short[] colours = this.faceColor;
            int[] realColours = new int[colours.length];
            for(int i = 0; i < colours.length; i++) {
                int colour = Utilities.hslToRgb(colours[i] & 0xffff);
                realColours[i] = colour;
                int r = (colour>>16)&0xFF;
                int g = (colour>>8)&0xFF;
                int b = (colour>>0)&0xFF;
            }
            this.realFaceColour = realColours;
        }
        void calculateMaxDepth(InputStream first, InputStream second) {
            short s_3 = 0;
            short s_4 = 0;
            short s_5 = 0;
            short s_6 = 0;
    
            for (int i_7 = 0; i_7 < faceCount; i_7++) {
                int i_8 = second.readUnsignedByte();
                if (i_8 == 1) {
                    s_3 = (short) (first.readUnsignedSmart2() + s_6);
                    s_4 = (short) (first.readUnsignedSmart2() + s_3);
                    s_5 = (short) (first.readUnsignedSmart2() + s_4);
                    s_6 = s_5;
                    triangleX[i_7] = s_3;
                    triangleY[i_7] = s_4;
                    triangleZ[i_7] = s_5;
                    if (s_3 > maxDepth) {
                        maxDepth = s_3;
                    }
    
                    if (s_4 > maxDepth) {
                        maxDepth = s_4;
                    }
    
                    if (s_5 > maxDepth) {
                        maxDepth = s_5;
                    }
                }
    
                if (i_8 == 2) {
                    s_4 = s_5;
                    s_5 = (short) (first.readUnsignedSmart2() + s_6);
                    s_6 = s_5;
                    triangleX[i_7] = s_3;
                    triangleY[i_7] = s_4;
                    triangleZ[i_7] = s_5;
                    if (s_5 > maxDepth) {
                        maxDepth = s_5;
                    }
                }
    
                if (i_8 == 3) {
                    s_3 = s_5;
                    s_5 = (short) (first.readUnsignedSmart2() + s_6);
                    s_6 = s_5;
                    triangleX[i_7] = s_3;
                    triangleY[i_7] = s_4;
                    triangleZ[i_7] = s_5;
                    if (s_5 > maxDepth) {
                        maxDepth = s_5;
                    }
                }
    
                if (i_8 == 4) {
                    short s_9 = s_3;
                    s_3 = s_4;
                    s_4 = s_9;
                    s_5 = (short) (first.readUnsignedSmart2() + s_6);
                    s_6 = s_5;
                    triangleX[i_7] = s_3;
                    triangleY[i_7] = s_9;
                    triangleZ[i_7] = s_5;
                    if (s_5 > maxDepth) {
                        maxDepth = s_5;
                    }
                }
            }
    
            ++maxDepth;
        }
    
        void decodeTexturedTriangles(InputStream first, InputStream second, InputStream third, InputStream fourth, InputStream fifth, InputStream sixth) {
            for (int i_7 = 0; i_7 < texturedFaceCount; i_7++) {
                int i_8 = textureRenderTypes[i_7] & 0xff;
                if (i_8 == 0) {
                    texTriX[i_7] = (short) first.readUnsignedShort();
                    texTriY[i_7] = (short) first.readUnsignedShort();
                    texTriZ[i_7] = (short) first.readUnsignedShort();
                }
    
                if (i_8 == 1) {
                    texTriX[i_7] = (short) second.readUnsignedShort();
                    texTriY[i_7] = (short) second.readUnsignedShort();
                    texTriZ[i_7] = (short) second.readUnsignedShort();
                    if (version < 15) {
                        particleDirectionX[i_7] = third.readUnsignedShort();
                        if (version < 14) {
                            particleDirectionY[i_7] = third.readUnsignedShort();
                        } else {
                            particleDirectionY[i_7] = third.read24BitUnsignedInt();
                        }
    
                        particleDirectionZ[i_7] = third.readUnsignedShort();
                    } else {
                        particleDirectionX[i_7] = third.read24BitUnsignedInt();
                        particleDirectionY[i_7] = third.read24BitUnsignedInt();
                        particleDirectionZ[i_7] = third.read24BitUnsignedInt();
                    }
    
                    particleLifespanX[i_7] = fourth.readByte();
                    particleLifespanY[i_7] = fifth.readByte();
                    particleLifespanZ[i_7] = sixth.readByte();
                }
    
                if (i_8 == 2) {
                    texTriX[i_7] = (short) second.readUnsignedShort();
                    texTriY[i_7] = (short) second.readUnsignedShort();
                    texTriZ[i_7] = (short) second.readUnsignedShort();
                    if (version < 15) {
                        particleDirectionX[i_7] = third.readUnsignedShort();
                        if (version < 14) {
                            particleDirectionY[i_7] = third.readUnsignedShort();
                        } else {
                            particleDirectionY[i_7] = third.read24BitUnsignedInt();
                        }
    
                        particleDirectionZ[i_7] = third.readUnsignedShort();
                    } else {
                        particleDirectionX[i_7] = third.read24BitUnsignedInt();
                        particleDirectionY[i_7] = third.read24BitUnsignedInt();
                        particleDirectionZ[i_7] = third.read24BitUnsignedInt();
                    }
    
                    particleLifespanX[i_7] = fourth.readByte();
                    particleLifespanY[i_7] = fifth.readByte();
                    particleLifespanZ[i_7] = sixth.readByte();
                    texturePrimaryColor[i_7] = sixth.readByte();
                    textureSecondaryColor[i_7] = sixth.readByte();
                }
    
                if (i_8 == 3) {
                    texTriX[i_7] = (short) second.readUnsignedShort();
                    texTriY[i_7] = (short) second.readUnsignedShort();
                    texTriZ[i_7] = (short) second.readUnsignedShort();
                    if (version < 15) {
                        particleDirectionX[i_7] = third.readUnsignedShort();
                        if (version < 14) {
                            particleDirectionY[i_7] = third.readUnsignedShort();
                        } else {
                            particleDirectionY[i_7] = third.read24BitUnsignedInt();
                        }
    
                        particleDirectionZ[i_7] = third.readUnsignedShort();
                    } else {
                        particleDirectionX[i_7] = third.read24BitUnsignedInt();
                        particleDirectionY[i_7] = third.read24BitUnsignedInt();
                        particleDirectionZ[i_7] = third.read24BitUnsignedInt();
                    }
    
                    particleLifespanX[i_7] = fourth.readByte();
                    particleLifespanY[i_7] = fifth.readByte();
                    particleLifespanZ[i_7] = sixth.readByte();
                }
            }
    
        }
    
        public RSMesh(RSMesh[] meshes, int size) {
            vertexCount = 0;
            faceCount = 0;
            texturedFaceCount = 0;
            int i_3 = 0;
            int i_4 = 0;
            int i_5 = 0;
            boolean faceTypes = false;
            boolean bool_7 = false;
            boolean bool_8 = false;
            boolean bool_9 = false;
            boolean bool_10 = false;
            boolean bool_11 = false;
            priority = -1;
    
            int index;
            for (index = 0; index < size; index++) {
                RSMesh mesh = meshes[index];
                if (mesh != null) {
                    vertexCount += mesh.vertexCount;
                    faceCount += mesh.faceCount;
                    texturedFaceCount += mesh.texturedFaceCount;
                    if (mesh.particleConfig != null) {
                        i_3 += mesh.particleConfig.length;
                    }
    
                    if (mesh.surfaceSkins != null) {
                        i_4 += mesh.surfaceSkins.length;
                    }
    
                    if (mesh.isolatedVertexNormals != null) {
                        i_5 += mesh.isolatedVertexNormals.length;
                    }
    
                    faceTypes |= mesh.faceType != null;
                    if (mesh.facePriorities != null) {
                        bool_7 = true;
                    } else {
                        if (priority == -1) {
                            priority = mesh.priority;
                        }
    
                        if (priority != mesh.priority) {
                            bool_7 = true;
                        }
                    }
    
                    bool_8 |= mesh.faceAlphas != null;
                    bool_9 |= mesh.texturePos != null;
                    bool_10 |= mesh.faceTextures != null;
                    bool_11 |= mesh.textureSkins != null;
                }
            }
    
            vertexX = new int[vertexCount];
            vertexY = new int[vertexCount];
            vertexZ = new int[vertexCount];
            vertexSkins = new int[vertexCount];
            aShortArray1980 = new short[vertexCount];
            triangleX = new short[faceCount];
            triangleY = new short[faceCount];
            triangleZ = new short[faceCount];
            if (faceTypes) {
                faceType = new byte[faceCount];
            }
    
            if (bool_7) {
                facePriorities = new byte[faceCount];
            }
    
            if (bool_8) {
                faceAlphas = new byte[faceCount];
            }
    
            if (bool_9) {
                texturePos = new byte[faceCount];
            }
    
            faceColor = new short[faceCount];
            if (bool_10) {
                faceTextures = new short[faceCount];
            }
    
            if (bool_11) {
                textureSkins = new int[faceCount];
            }
    
            aShortArray1981 = new short[faceCount];
            if (texturedFaceCount > 0) {
                textureRenderTypes = new int[texturedFaceCount];
                texTriX = new short[texturedFaceCount];
                texTriY = new short[texturedFaceCount];
                texTriZ = new short[texturedFaceCount];
                particleDirectionX = new int[texturedFaceCount];
                particleDirectionY = new int[texturedFaceCount];
                particleDirectionZ = new int[texturedFaceCount];
                particleLifespanX = new int[texturedFaceCount];
                particleLifespanY = new int[texturedFaceCount];
                particleLifespanZ = new int[texturedFaceCount];
                texturePrimaryColor = new int[texturedFaceCount];
                textureSecondaryColor = new int[texturedFaceCount];
            }
    
            if (i_5 > 0) {
                isolatedVertexNormals = new VertexNormal[i_5];
            }
    
            if (i_3 > 0) {
                particleConfig = new ParticleEmitterConfig[i_3];
            }
    
            if (i_4 > 0) {
                surfaceSkins = new SurfaceSkin[i_4];
            }
    
            vertexCount = 0;
            faceCount = 0;
            texturedFaceCount = 0;
            i_3 = 0;
            i_4 = 0;
            i_5 = 0;
    
            int i_16;
            for (index = 0; index < size; index++) {
                short s_13 = (short) (1 << index);
                RSMesh rsmesh_14 = meshes[index];
                if (rsmesh_14 != null) {
                    int i_15;
                    if (rsmesh_14.isolatedVertexNormals != null) {
                        for (i_15 = 0; i_15 < rsmesh_14.isolatedVertexNormals.length; i_15++) {
                            VertexNormal normals = rsmesh_14.isolatedVertexNormals[i_15];
                            isolatedVertexNormals[i_5++] = normals.method1459(normals.anInt809 + faceCount);
                        }
                    }
    
                    for (i_15 = 0; i_15 < rsmesh_14.faceCount; i_15++) {
                        if (faceTypes && rsmesh_14.faceType != null) {
                            faceType[faceCount] = rsmesh_14.faceType[i_15];
                        }
    
                        if (bool_7) {
                            if (rsmesh_14.facePriorities != null) {
                                facePriorities[faceCount] = rsmesh_14.facePriorities[i_15];
                            } else {
                                facePriorities[faceCount] = rsmesh_14.priority;
                            }
                        }
    
                        if (bool_8 && rsmesh_14.faceAlphas != null) {
                            faceAlphas[faceCount] = rsmesh_14.faceAlphas[i_15];
                        }
    
                        if (bool_10) {
                            if (rsmesh_14.faceTextures != null) {
                                faceTextures[faceCount] = rsmesh_14.faceTextures[i_15];
                            } else {
                                faceTextures[faceCount] = -1;
                            }
                        }
    
                        if (bool_11) {
                            if (rsmesh_14.textureSkins != null) {
                                textureSkins[faceCount] = rsmesh_14.textureSkins[i_15];
                            } else {
                                textureSkins[faceCount] = -1;
                            }
                        }
    
                        triangleX[faceCount] = (short) method2657(rsmesh_14, rsmesh_14.triangleX[i_15], s_13);
                        triangleY[faceCount] = (short) method2657(rsmesh_14, rsmesh_14.triangleY[i_15], s_13);
                        triangleZ[faceCount] = (short) method2657(rsmesh_14, rsmesh_14.triangleZ[i_15], s_13);
                        aShortArray1981[faceCount] = s_13;
                        faceColor[faceCount] = rsmesh_14.faceColor[i_15];
                        ++faceCount;
                    }
    
                    if (rsmesh_14.particleConfig != null) {
                        for (i_15 = 0; i_15 < rsmesh_14.particleConfig.length; i_15++) {
                            i_16 = method2657(rsmesh_14, rsmesh_14.particleConfig[i_15].faceX, s_13);
                            int i_17 = method2657(rsmesh_14, rsmesh_14.particleConfig[i_15].faceY, s_13);
                            int i_18 = method2657(rsmesh_14, rsmesh_14.particleConfig[i_15].faceZ, s_13);
                            particleConfig[i_3] = rsmesh_14.particleConfig[i_15].method1488(i_16, i_17, i_18);
                            ++i_3;
                        }
                    }
    
                    if (rsmesh_14.surfaceSkins != null) {
                        for (i_15 = 0; i_15 < rsmesh_14.surfaceSkins.length; i_15++) {
                            i_16 = method2657(rsmesh_14, rsmesh_14.surfaceSkins[i_15].anInt2119, s_13);
                            surfaceSkins[i_4] = rsmesh_14.surfaceSkins[i_15].method2911(i_16);
                            ++i_4;
                        }
                    }
                }
            }
    
            index = 0;
            maxDepth = vertexCount;
    
            for (int i_23 = 0; i_23 < size; i_23++) {
                short s_19 = (short) (1 << i_23);
                RSMesh rsmesh_20 = meshes[i_23];
                if (rsmesh_20 != null) {
                    for (i_16 = 0; i_16 < rsmesh_20.faceCount; i_16++) {
                        if (bool_9) {
                            texturePos[index++] = (byte) (rsmesh_20.texturePos != null && rsmesh_20.texturePos[i_16] != -1 ? texturedFaceCount + rsmesh_20.texturePos[i_16] : -1);
                        }
                    }
    
                    for (i_16 = 0; i_16 < rsmesh_20.texturedFaceCount; i_16++) {
                        int b_24 = textureRenderTypes[texturedFaceCount] = rsmesh_20.textureRenderTypes[i_16];
                        if (b_24 == 0) {
                            texTriX[texturedFaceCount] = (short) method2657(rsmesh_20, rsmesh_20.texTriX[i_16], s_19);
                            texTriY[texturedFaceCount] = (short) method2657(rsmesh_20, rsmesh_20.texTriY[i_16], s_19);
                            texTriZ[texturedFaceCount] = (short) method2657(rsmesh_20, rsmesh_20.texTriZ[i_16], s_19);
                        }
    
                        if (b_24 >= 1 && b_24 <= 3) {
                            texTriX[texturedFaceCount] = rsmesh_20.texTriX[i_16];
                            texTriY[texturedFaceCount] = rsmesh_20.texTriY[i_16];
                            texTriZ[texturedFaceCount] = rsmesh_20.texTriZ[i_16];
                            particleDirectionX[texturedFaceCount] = rsmesh_20.particleDirectionX[i_16];
                            particleDirectionY[texturedFaceCount] = rsmesh_20.particleDirectionY[i_16];
                            particleDirectionZ[texturedFaceCount] = rsmesh_20.particleDirectionZ[i_16];
                            particleLifespanX[texturedFaceCount] = rsmesh_20.particleLifespanX[i_16];
                            particleLifespanY[texturedFaceCount] = rsmesh_20.particleLifespanY[i_16];
                            particleLifespanZ[texturedFaceCount] = rsmesh_20.particleLifespanZ[i_16];
                        }
    
                        if (b_24 == 2) {
                            texturePrimaryColor[texturedFaceCount] = rsmesh_20.texturePrimaryColor[i_16];
                            textureSecondaryColor[texturedFaceCount] = rsmesh_20.textureSecondaryColor[i_16];
                        }
    
                        ++texturedFaceCount;
                    }
                }
            }
    
        }
    
        public void recolour(short s_1, short s_2) {
            for (int i_3 = 0; i_3 < faceCount; i_3++) {
                if (faceColor[i_3] == s_1) {
                    faceColor[i_3] = s_2;
                }
            }
    
        }
    
        public void retexture(short s_1, short s_2) {
            if (faceTextures != null) {
                for (int i_3 = 0; i_3 < faceCount; i_3++) {
                    if (faceTextures[i_3] == s_1) {
                        faceTextures[i_3] = s_2;
                    }
                }
            }
    
        }
    
        int method2657(RSMesh rsmesh_1, int i_2, short s_3) {
            int i_4 = rsmesh_1.vertexX[i_2];
            int i_5 = rsmesh_1.vertexY[i_2];
            int i_6 = rsmesh_1.vertexZ[i_2];
    
            for (int i_7 = 0; i_7 < vertexCount; i_7++) {
                if (i_4 == vertexX[i_7] && i_5 == vertexY[i_7] && i_6 == vertexZ[i_7]) {
                    aShortArray1980[i_7] |= s_3;
                    return i_7;
                }
            }
    
            vertexX[vertexCount] = i_4;
            vertexY[vertexCount] = i_5;
            vertexZ[vertexCount] = i_6;
            aShortArray1980[vertexCount] = s_3;
            vertexSkins[vertexCount] = rsmesh_1.vertexSkins != null ? rsmesh_1.vertexSkins[i_2] : -1;
            return vertexCount++;
        }
    
        public void upscale() {
            int i_2;
            for (i_2 = 0; i_2 < vertexCount; i_2++) {
                vertexX[i_2] <<= 2;
                vertexY[i_2] <<= 2;
                vertexZ[i_2] <<= 2;
            }
    
            if (texturedFaceCount > 0 && particleDirectionX != null) {
                for (i_2 = 0; i_2 < particleDirectionX.length; i_2++) {
                    particleDirectionX[i_2] <<= 2;
                    particleDirectionY[i_2] <<= 2;
                    if (textureRenderTypes[i_2] != 1) {
                        particleDirectionZ[i_2] <<= 2;
                    }
                }
            }
    
        }
    }
    Code:
    package com.cryo.cache.loaders;
    
    import com.cryo.cache.Cache;
    import com.cryo.cache.FileType;
    import com.cryo.cache.IndexType;
    import com.cryo.cache.io.InputStream;
    import com.cryo.cache.loaders.model.ModelDefinitions;
    import com.cryo.cache.loaders.model.RSMesh;
    
    import java.util.Arrays;
    import java.util.HashMap;
    
    public class IdentiKitDefinition {
    
        private int id;
        private int[] modelIds;
        private short[] originalColours;
        private short[] replacementColours;
        private short[] originalTextures;
        private short[] replacementTextures;
        private int[] headModels = {-1, -1, -1, -1, -1};
    
        private static HashMap<Integer, IdentiKitDefinition> defs = new HashMap<>();
    
        public static IdentiKitDefinition getIdentikitDefinition(int id) {
            if (defs.containsKey(id)) return defs.get(id);
            byte[] data = Cache.STORE.getIndex(IndexType.CONFIG).getFile(FileType.IDENTIKIT.getId(), id);
            if (data == null) return null;
            IdentiKitDefinition defs = new IdentiKitDefinition(id);
            defs.decode(new InputStream(data));
            IdentiKitDefinition.defs.put(id, defs);
            return defs;
        }
    
        public IdentiKitDefinition(int id) {
            this.id = id;
        }
    
        public RSMesh renderHead(boolean upscale) {
            RSMesh[] meshes = new RSMesh[5];
            int index = 0;
            for (int i = 0; i < 5; i++) {
                if (headModels[i] != -1) {
                    ModelDefinitions defs = ModelDefinitions.getModelDefinitions(headModels[i]);
                    if (defs != null)
                        meshes[index++] = defs.getMesh();
                }
            }
            for (int i = 0; i < 5; i++) {
                if (meshes[i] != null && meshes[i].version < 13)
                    meshes[i].upscale();
            }
            RSMesh mesh = new RSMesh(meshes, index);
            if (originalColours != null) {
                for (int i = 0; i < originalColours.length; i++) {
                    mesh.recolour(originalColours[i], replacementColours[i]);
                }
            }
            if (originalTextures != null) {
                for (int i = 0; i < originalTextures.length; i++) {
                    mesh.retexture(originalTextures[i], replacementTextures[i]);
                }
            }
            return mesh;
        }
    
        public RSMesh renderBody() {
            if (modelIds == null)
                return null;
            RSMesh[] meshes = new RSMesh[modelIds.length];
            int index = 0;
            while (index < modelIds.length) {
                meshes[index] = ModelDefinitions.getModelDefinitions(modelIds[index]).getMesh();
                ++index;
            }
            for (int i_5 = 0; i_5 < modelIds.length; i_5++) {
                if (meshes[i_5].version < 13) {
                    meshes[i_5].upscale();
                }
            }
            RSMesh mesh = meshes.length == 1 ? meshes[0] : new RSMesh(meshes, meshes.length);
            if (mesh == null)
                return null;
            if (originalColours != null) {
                for (index = 0; index < originalColours.length; index++) {
                    mesh.recolour(originalColours[index], replacementColours[index]);
                }
            }
            if (originalTextures != null) {
                for (index = 0; index < originalTextures.length; index++) {
                    mesh.retexture(originalTextures[index], replacementTextures[index]);
                }
            }
            return mesh;
        }
    
        public void decode(int opcode, InputStream stream) {
            if (opcode == 1)
                stream.readUnsignedByte();
            else if (opcode == 2) {
                int count = stream.readUnsignedByte();
                modelIds = new int[count];
                for (int i = 0; i < count; i++) {
                    modelIds[i] = stream.readBigSmart();
                }
            } else if (opcode == 40) {
                int count = stream.readUnsignedByte();
                originalColours = new short[count];
                replacementColours = new short[count];
                for (int i = 0; i < count; i++) {
                    originalColours[i] = (short) stream.readUnsignedShort();
                    replacementColours[i] = (short) stream.readUnsignedShort();
                }
            } else if (opcode == 41) {
                int count = stream.readUnsignedByte();
                originalTextures = new short[count];
                replacementTextures = new short[count];
                for (int i = 0; i < count; i++) {
                    originalTextures[i] = (short) stream.readUnsignedShort();
                    replacementTextures[i] = (short) stream.readUnsignedShort();
                }
            } else if (opcode >= 60 && opcode < 70) {
                headModels[opcode - 60] = stream.readBigSmart();
            }
        }
    
        public void decode(InputStream stream) {
            while (true) {
                int opcode = stream.readUnsignedByte();
                if (opcode == 0) break;
                decode(opcode, stream);
            }
        }
    }
    Code:
        public RSMesh getBodyMesh(boolean isFemale, MeshModifier modifier) {
            int equip1;
            int equip2;
            int equip3;
            if (isFemale) {
                if (modifier != null && modifier.femaleBody != null) {
                    equip1 = modifier.femaleBody[0];
                    equip2 = modifier.femaleBody[1];
                    equip3 = modifier.femaleBody[2];
                } else {
                    equip1 = femaleEquip1;
                    equip2 = femaleEquip2;
                    equip3 = femaleEquip3;
                }
            } else if (modifier != null && modifier.maleBody != null) {
                equip1 = modifier.maleBody[0];
                equip2 = modifier.maleBody[1];
                equip3 = modifier.maleBody[2];
            } else {
                equip1 = maleEquip1;
                equip2 = maleEquip2;
                equip3 = maleEquip3;
            }
            if (equip1 == -1)
                return null;
            ModelDefinitions defs = ModelDefinitions.getModelDefinitions(equip1);
            if(defs == null)
                return null;
            RSMesh mesh = defs.getMesh();
            if (mesh == null)
                return null;
            if (mesh.version < 13)
                mesh.upscale();
            if (equip2 != -1) {
                RSMesh equip2Mesh = ModelDefinitions.getModelDefinitions(equip2).getMesh();
                if (equip2Mesh.version < 13)
                    equip2Mesh.upscale();
                if (equip3 != -1) {
                    RSMesh equip3Mesh = ModelDefinitions.getModelDefinitions(equip3).getMesh();
                    if (equip3Mesh.version < 13)
                        equip3Mesh.upscale();
                    RSMesh[] meshes = {mesh, equip2Mesh, equip3Mesh};
                    mesh = new RSMesh(meshes, 3);
                } else {
                    RSMesh[] meshes = {mesh, equip2Mesh};
                    mesh = new RSMesh(meshes, 2);
                }
            }
    //        if (!isFemale && (maleWearXOffset != 0 || maleWearYOffset != 0 || maleWearZOffset != 0))
    //            mesh.translate(maleWearXOffset, maleWearYOffset, maleWearZOffset);
    //        if (isFemale && (femaleWearXOffset != 0 || femaleWearYOffset != 0 || femaleWearZOffset != 0))
    //            mesh.translate(femaleWearXOffset, femaleWearYOffset, femaleWearZOffset);
            int i;
            short[] modified;
            if (originalModelColours != null) {
                if (modifier != null && modifier.modifiedColours != null)
                    modified = modifier.modifiedColours;
                else
                    modified = modifiedModelColours;
                System.out.println("MODIFYING COLOURS: "+Arrays.toString(originalModelColours));
                for (i = 0; i < originalModelColours.length; i++)
                    mesh.recolour(originalModelColours[i], modified[i]);
            }
            if (originalTextureIds != null) {
                if (modifier != null && modifier.modifiedTextures != null)
                    modified = modifier.modifiedTextures;
                else
                    modified = modifiedTextureIds;
                for (i = 0; i < originalTextureIds.length; i++)
                    mesh.retexture(originalTextureIds[i], modified[i]);
            }
            return mesh;
        }
    
        public RSMesh getHeadMesh(boolean isFemale, MeshModifier modifier) {
            int headModel1;
            int headModel2;
            if (isFemale) {
                if (modifier != null && modifier.femaleHead != null) {
                    headModel1 = modifier.femaleHead[0];
                    headModel2 = modifier.femaleHead[1];
                } else {
                    headModel1 = femaleHead1;
                    headModel2 = femaleHead2;
                }
            } else if (modifier != null && modifier.maleHead != null) {
                headModel1 = modifier.maleHead[0];
                headModel2 = modifier.maleHead[1];
            } else {
                headModel1 = maleHead1;
                headModel2 = maleHead2;
            }
            if (headModel1 == -1)
                return null;
            RSMesh mesh = ModelDefinitions.getModelDefinitions(headModel1).getMesh();
            if (mesh.version < 13)
                mesh.upscale();
            if (headModel2 != -1) {
                RSMesh mesh2 = ModelDefinitions.getModelDefinitions(headModel2).getMesh();
                if (mesh2.version < 13)
                    mesh2.upscale();
                RSMesh[] meshes = {mesh, mesh2};
                mesh = new RSMesh(meshes, 2);
            }
            int i;
            short[] modified;
            if (originalModelColours != null) {
                if (modifier != null && modifier.modifiedColours != null)
                    modified = modifier.modifiedColours;
                else
                    modified = modifiedModelColours;
                for (i = 0; i < originalModelColours.length; i++)
                    mesh.recolour(originalModelColours[i], modified[i]);
            }
            if (originalTextureIds != null) {
                if (modifier != null && modifier.modifiedTextures != null)
                    modified = modifier.modifiedTextures;
                else
                    modified = modifiedTextureIds;
                for (i = 0; i < originalTextureIds.length; i++)
                    mesh.retexture(originalTextureIds[i], modified[i]);
            }
            return mesh;
        }
    Credits:
    Makar: 727 client for reference
    Countless people on r-s for releasing the model header
    Reply With Quote  
     


  2. #2  
    *breaks walking*

    Cody_'s Avatar
    Join Date
    Dec 2010
    Posts
    721
    Thanks given
    204
    Thanks received
    189
    Discord
    View profile
    Rep Power
    267
    Can't seem to update original post at the moment. But I've got animations working, and I'll add it to the post when I can.



    Next to tackle is materials/textures I suppose.
    Reply With Quote  
     

  3. Thankful user:


  4. #3  
    what the dog doin

    Rebecca's Avatar
    Join Date
    Aug 2017
    Posts
    967
    Thanks given
    774
    Thanks received
    815
    Discord
    View profile
    Rep Power
    5000
    interesting, gj
    Reply With Quote  
     

  5. #4  






    Omar's Avatar
    Join Date
    Dec 2007
    Posts
    251
    Thanks given
    505
    Thanks received
    669
    Discord
    View profile
    Rep Power
    5000
    actually pretty cool. nice job


    Spoiler for aaaa:



    Reply With Quote  
     

  6. #5  
    *breaks walking*

    Cody_'s Avatar
    Join Date
    Dec 2010
    Posts
    721
    Thanks given
    204
    Thanks received
    189
    Discord
    View profile
    Rep Power
    267
    Still can't seem to edit the main post if I'm editing as much as I am. Just times out to a 'cannot complete request'.

    Until I can, here's the updated info needed for animations:

    Updated model-viewer.js

    Code:
    let renderer;
    let scene;
    let camera;
    
    let cube;
    
    let controls;
    
    let animation;
    let rasterizer;
    
    let renderId;
    let temporaryId = -1;
    
    function loadScene(model) {
        console.log(model);
        scene = new THREE.Scene();
    
        let width = 250;
        let height = 400;
    
        camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 6000);
    
        renderer = new THREE.WebGLRenderer();
        renderer.setSize(width, height);
    
        $('#model-viewer').append(renderer.domElement);
    
        //ADD CUBE
        let vertices = [];
    
        let hasAlpha = model.FaceAlphas != null;
        let hasFaceTypes = model.FaceType != null;
    
        //BUILD GEOMETRY
        for (let i = 0; i < model.FaceCount; i++) {
    
            let alpha = hasAlpha ? model.FaceAlphas[i] : 0;
            if (alpha == -1) continue;
    
            alpha = ~alpha & 0xFF;
            let faceType = hasFaceTypes ? model.FaceType[i] & 0x3 : 0;
    
            let faceA, faceB, faceC;
            switch (faceType) {
                case 0:
                case 1:
                    faceA = model.TriangleX[i];
                    faceB = model.TriangleY[i];
                    faceC = model.TriangleZ[i];
                    break;
                case 2:
                case 3:
                    faceA = model.TexTriX[i];
                    faceB = model.TexTriY[i];
                    faceC = model.TexTriZ[i];
                    break;
                default:
                    throw new Error('Unknown face type=' + faceType);
            }
    
            let textureId = model.FaceTextures == null ? -1 : model.FaceTextures[i];
    
            let u, v;
            let colour = model.RealFaceColour[i];
            let r = (colour >> 16) & 0xFF;
            let g = (colour >> 8) & 0xFF;
            let b = colour & 0xFF;
            vertices.push({ pos: [model.VertexX[faceA], model.VertexY[faceA], model.VertexZ[faceA]], norm: [faceA, faceB, faceC], colors: [r, g, b, alpha] });
            vertices.push({ pos: [model.VertexX[faceB], model.VertexY[faceB], model.VertexZ[faceB]], norm: [faceA, faceB, faceC], colors: [r, g, b, alpha] });
            vertices.push({ pos: [model.VertexX[faceC], model.VertexY[faceC], model.VertexZ[faceC]], norm: [faceA, faceB, faceC], colors: [r, g, b, alpha] });
        }
    
        let positions = [];
        let normals = [];
        let colors = [];
        for (let vertex of vertices) {
            positions.push(...vertex.pos);
            normals.push(...vertex.norm);
            colors.push(...vertex.colors);
        }
    
        let geometry = new THREE.BufferGeometry();
        geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(positions), 3));
        geometry.setAttribute('normal', new THREE.BufferAttribute(new Float32Array(normals), 3));
        geometry.addAttribute('color', new THREE.BufferAttribute(new Uint8Array(colors), 4, true));
    
        geometry.normalizeNormals();
        geometry.computeVertexNormals();
    
    
        let material = new THREE.MeshBasicMaterial({ vertexColors: THREE.VertexColors });
        cube = new THREE.Mesh(geometry, material);
    
        cube.rotation.x = Math.PI; //model renders upside down for some reason
    
        scene.add(cube);
        camera.position.z = 3000;
    
        controls = new THREE.TrackballControls(camera, renderer.domElement);
        controls.target.set(0, 500, 0);
    
        controls.addEventListener('end', function() {
    
        });
    
        controls.noPan = true;
        controls.rotateSpeed = 0.03;
    
        renderId = parseInt('!{animationId}');
    
        rasterizer = new Rasterizer.Rasterizer(model, cube);
        animation = new Animation.Animation();
        animation.setupAnimation(renderId, model.Animation);
    
        let playable = false;
    
        animate();
    
        setInterval(async function() {
            if (playable) return;
    
            if (animation.setupLoop(1) && animation.getABool5462()) {
                if (temporaryId != -1) {
                    animation.setupAnimation(renderId, model.Animation);
                    temporaryId = -1;
                }
                animation.resetAnimation();
            }
            playable = true;
            if (animation != null)
                await animation.rasterize(rasterizer, 0);
            playable = false;
        }, 20);
    }
    
    function animate() {
        requestAnimationFrame(animate);
    
        controls.update();
    
        renderer.render(scene, camera);
    }
    And information for animations:
    Spoiler for Animations:

    The following are the JS files needed for animations. The definitions need to be loaded server sided, and added to the mesh. You can see how we grab that data in the model-viewer.js file above.
    The definitions can be taken from the client. Suggestion: https://github.com/titandino/darkan-game-client

    Code:
    var Animation = Animation || {};
    
    Animation.Animation = function Animation() {
    
        this.frameManager = new FrameManager.FrameManager();
    
        this.setupAnimation = function(id, defs, speed = 0, i_3 = 0, bool_4 = false, bool_5 = true) {
            if (id == this.getCurrentAnimation()) return;
            if (id == -1) {
                this.id = -1;
                this.defs = null;
                this.resetFrames();
                return;
            }
            if (this.defs != null && this.defs.Id == id) {
                if (this.defs.ReplayMode == 0) return;
            } else
                this.defs = defs;
            this.anInt5459 = 0;
            this.speed = speed;
            this.anInt5461 = i_3;
            this.aBool5456 = bool_5;
            if (bool_4) {
                this.frame1Index = (Math.random() * this.defs.FrameHashes.length);
                this.frame1Duration = (Math.random() * this.defs.FrameDurations[this.frame1Index]);
            } else {
                this.frame1Index = 0;
                this.frame1Duration = 0;
            }
            this.frame2Index = this.frame1Index + 1;
            if (this.frame2Index >= this.defs.FrameHashes.length)
                this.frame2Index = -1;
            if (this.speed == 0) {
                //play animation sound
            }
            this.aBool5462 = false;
            this.resetFrames();
        }
    
        this.increaseIndex = function() {
            this.frame1Index++;
            this.frame2Index++;
            if (this.frame2Index >= this.defs.FrameHashes.length)
                this.frame2Index = 0;
        }
    
        this.getABool5462 = function() {
            return this.aBool5462 == true;
        }
    
        this.setupLoop = function(loopStart) {
            if (this.defs == null || loopStart == 0) return false;
            if (this.speed > 0) {
                if (this.speed >= loopStart) {
                    this.speed -= loopStart;
                    return false;
                }
                loopStart -= this.speed;
                this.speed = 0;
                //play animation sound
            }
            loopStart += this.frame1Duration;
            let bool_3 = this.defs.Tweened;
            if (loopStart > 100 && this.defs.LoopDelay > 0) {
                let i_4;
                for (let i_4 = this.defs.FrameHashes.length - this.defs.LoopDelay; this.frame1Index < i_4 && loopStart > this.defs.FrameDurations[this.frame1Index]; this.frame1Index++)
                    loopStart -= this.defs.FrameDurations[this.frame1Index];
                if (this.frame1Index >= i_4) {
                    let totalDuration = 0;
                    for (let i = i_4; i < this.defs.FrameHashes.length; i++)
                        totalDuration += this.defs.FrameDurations[i];
                    if (this.anInt5461 == 0)
                        this.anInt5459 += loopStart / totalDuration;
                    loopStart %= totalDuration;
                }
                this.frame2Index = this.frame1Index + 1;
                if (this.frame2Index >= this.defs.FrameHashes.length) {
                    if (this.defs.LoopDelay == -1 && this.aBool5456 == true)
                        this.frame2Index = 0;
                    else
                        this.frame2Index -= this.defs.LoopDelay;
                    if (this.frame2Index < 0 || this.frame2Index >= this.defs.FrameHashes.length)
                        this.frame2Index = -1;
                }
                bool_3 = true;
            }
            while (loopStart > this.defs.FrameDurations[this.frame1Index]) {
                bool_3 = true;
                loopStart -= this.defs.FrameDurations[this.frame1Index++];
                if (this.frame1Index >= this.defs.FrameHashes.length) {
                    if (this.defs.LoopDelay != -1 && this.anInt5461 != 2) {
                        this.frame1Index -= this.defs.LoopDelay;
                        if (this.anInt5461 == 0)
                            this.anInt5459++;
                    }
                    if (this.anInt5459 >= this.defs.MaxLoops || this.frame1Index < 0 || this.frame1Index >= this.defs.FrameHashes.length) {
                        this.aBool5462 = true;
                        break;
                    }
                }
                //play sound
                this.frame2Index = this.frame1Index + 1;
                if (this.frame2Index >= this.defs.FrameHashes.length) {
                    if (this.defs.LoopDelay == -1 && this.aBool5456 == true)
                        this.frame2Index = 0;
                    else
                        this.frame2Index -= this.defs.LoopDelay;
                    if (this.frame2Index < 0 || this.frame2Index >= this.defs.FrameHashes.length)
                        this.frame2Index = -1;
                }
            }
            this.frame1Duration = loopStart;
            if (bool_3)
                this.resetFrames();
            return bool_3;
        }
    
        this.resetFrames = function() {
            this.frameManager.resetFrames();
        }
    
        this.resetAnimation = function() {
            this.frame1Index = 0;
            this.frame2Index = this.defs.FrameHashes.length > 1 ? 1 : -1;
            this.frame1Duration = 0;
            this.aBool5462 = false;
            this.speed = 0;
            this.anInt5459 = 0;
            this.resetFrames();
        }
    
        this.rasterize = async function(rasterizer, i_2) {
            if (this.defs == null || this.defs.FrameHashes == null) return;
            let setup = await this.setupAnimationFrames();
            if (setup == true)
                rasterizer.rasterize(this.frameManager.frameSet1, this.frameManager.frame1Id, this.frameManager.frameSet2, this.frameManager.frame2Id, this.frame1Duration, this.defs.FrameDurations[this.frame1Index], i_2, this.defs.ABool5923);
        }
    
        this.setupAnimationFrames = async function() {
            if (this.defs == null) return false;
            let setup = await this.frameManager.setupAnimationFrame(this.defs, this.frame1Index, this.frame2Index, this.defs.FrameHashes);
            return setup;
        }
    
        this.getCurrentAnimation = function() {
            return this.defs != null ? this.defs.Id : -1;
        }
    
    }
    Code:
    var Rasterizer = Rasterizer || {};
    
    Rasterizer.Rasterizer = function Rasterizer(model, cube) {
    
        this.model = model;
        this.cube = cube;
        this.aBool7023 = false;
        this.aBool8589 = false;
        this.aBool8609 = false;
    
        this.vertexCount = model.VertexCount;
        this.faceCount = model.FaceCount;
        this.vertexX = JSON.parse(JSON.stringify(model.VertexX));
        this.vertexY = JSON.parse(JSON.stringify(model.VertexY));
        this.vertexZ = JSON.parse(JSON.stringify(model.VertexZ));
    
        this.xOffset = 0;
        this.yOffset = 0;
        this.zOffset = 0;
    
        this.count = 0;
    
        this.bones = this.model.AnimationBones;
    
        this.trig = new Trig.Trig();
    
        this.rasterize = function(frameSet1, frame1Id, frameSet2, frame2Id, i_5, i_6, i_7, bool_8) {
            if (frame1Id == -1) return;
            this.vertexX = JSON.parse(JSON.stringify(this.model.VertexX));
            this.vertexY = JSON.parse(JSON.stringify(this.model.VertexY));
            this.vertexZ = JSON.parse(JSON.stringify(this.model.VertexZ));
            if (this.ea()) {
                let frame1 = frameSet1.Frames[frame1Id];
                let frameBase = frame1.FrameBase;
                let frame2 = null;
                if (frameSet2 != null) {
                    frame2 = frameSet2.Frames[frame2Id];
                    if (frameBase.Id != frame2.FrameBase.Id)
                        frame2 = null;
                }
                this.beginTransformation(frameBase, frame1, frame2, i_5, i_6, i_7, null, false, bool_8, 65535, null);
                this.ka();
                // this.roundToInts();
                this.updateModel();
            }
        }
    
        this.updateModel = function() {
            let vertices = [];
    
            let hasAlpha = this.model.FaceAlphas != null;
            let hasFaceTypes = this.model.FaceType != null;
    
            for (let i = 0; i < this.model.FaceCount; i++) {
    
                let alpha = hasAlpha ? this.model.FaceAlphas[i] : 0;
                if (alpha == -1) continue;
    
                let faceType = hasFaceTypes ? this.model.FaceType[i] & 0x3 : 0;
    
                let faceA, faceB, faceC;
                switch (faceType) {
                    case 0:
                    case 1:
                        faceA = this.model.TriangleX[i];
                        faceB = this.model.TriangleY[i];
                        faceC = this.model.TriangleZ[i];
                        break;
                    case 2:
                    case 3:
                        faceA = this.model.TexTriX[i];
                        faceB = this.model.TexTriY[i];
                        faceC = this.model.TexTriZ[i];
                        break;
                    default:
                        throw new Error('Unknown face type=' + faceType);
                }
    
                vertices.push({ pos: [this.vertexX[faceA], this.vertexY[faceA], this.vertexZ[faceA]], norm: [faceA, faceB, faceC] });
                vertices.push({ pos: [this.vertexX[faceB], this.vertexY[faceB], this.vertexZ[faceB]], norm: [faceA, faceB, faceC] });
                vertices.push({ pos: [this.vertexX[faceC], this.vertexY[faceC], this.vertexZ[faceC]], norm: [faceA, faceB, faceC] });
            }
    
            let positions = [];
            let normals = [];
            for (let vertex of vertices) {
                positions.push(...vertex.pos);
                normals.push(...vertex.norm);
            }
    
            this.cube.geometry.attributes.position.array = new Float32Array(positions);
            this.cube.geometry.attributes.position.needsUpdate = true;
        }
    
        this.roundToInts = function() {
            for (let i = 0; i < this.vertexX.length; i++)
                this.vertexX[i] = Math.floor(this.vertexX[i]);
    
            for (let i = 0; i < this.vertexY.length; i++)
                this.vertexY[i] = Math.floor(this.vertexY[i]);
    
            for (let i = 0; i < this.vertexZ.length; i++)
                this.vertexZ[i] = Math.floor(this.vertexZ[i]);
        }
    
        this.ka = function() {
            if (this.aBool8589 == true) {
                for (let i = 0; i < this.vertexCount; i++) {
                    this.vertexX[i] = this.vertexX[i] + 7 >> 4;
                    this.vertexY[i] = this.vertexY[i] + 7 >> 4;
                    this.vertexZ[i] = this.vertexZ[i] + 7 >> 4;
                }
                this.aBool8589 = false;
            }
    
            if (this.aBool8609 == true) {
                this.method13801();
                this.aBool8609 = false;
            }
    
            this.aBool8621 = false;
        }
    
        this.method13801 = function() {
            //missing some shit
            this.method13802();
        }
    
        this.method13802 = function() {
            for (let i = 0; i < faceCount; i++) {
    
            }
        }
    
        this.ea = function() {
            if (this.bones == null)
                return false;
            this.xOffset = 0;
            this.yOffset = 0;
            this.zOffset = 0;
            return true;
        }
    
        this.beginTransformation = function(frameBase, frame1, frame2, i_4, i_5, i_6, bools_7, bool_8, bool_9, modelIndex, ints_11) {
            let i_12;
            if (frame2 != null && i_4 != 0) {
                i_12 = 0;
                let i_35 = 0;
                for (let index = 0; index < frameBase.Count; index++) {
                    let bool_15 = false;
                    if (i_12 < frame1.TransformationCount && index == frame1.TransformationIndices[i_12])
                        bool_15 = true;
    
                    let bool_16 = false;
                    if (i_35 < frame2.TransformationCount && index == frame2.TransformationIndices[i_35])
                        bool_16 = true;
    
                    if (bool_15 == true || bool_16 == true) {
                        if (bools_7 != null && bools_7[index] != bool_8 && frameBase.TransformationTypes[index] != 0) {
                            if (bool_15)
                                i_12++;
    
                            if (bool_16)
                                i_35++;
                        } else {
                            let s_17 = 0;
                            let type = frameBase.TransformationTypes[index];
                            if (type == 3 || type == 10)
                                s_17 = 128;
    
                            let frame1TransformX, frame1TransformY, frame1TransformZ, frame1Skip, frame1Flag;
                            let frame2TransformX, frame2TransformY, frame2TransformZ, frame2Skip, frame2Flag;
    
                            if (bool_15) {
                                frame1TransformX = frame1.TransformationX[i_12];
                                frame1TransformY = frame1.TransformationY[i_12];
                                frame1TransformZ = frame1.TransformationZ[i_12];
                                frame1Skip = frame1.SkippedReferences[i_12];
                                frame1Flag = frame1.TransformationFlags[i_12];
                                i_12++;
                            } else {
                                frame1TransformX = s_17;
                                frame1TransformY = s_17;
                                frame1TransformZ = s_17;
                                frame1Skip = -1;
                                frame1Flag = 0;
                            }
    
                            if (bool_16) {
                                frame2TransformX = frame2.TransformationX[i_35];
                                frame2TransformY = frame2.TransformationY[i_35];
                                frame2TransformZ = frame2.TransformationZ[i_35];
                                frame2Skip = frame2.SkippedReferences[i_35];
                                frame2Flag = frame2.TransformationFlags[i_35];
                                i_35++;
                            } else {
                                frame2TransformX = s_17;
                                frame2TransformY = s_17;
                                frame2TransformZ = s_17;
                                frame2Skip = -1;
                                frame2Flag = 0;
                            }
    
                            let x, y, z;
                            if ((frame1Flag & 0x2) == 0 && (frame2Flag & 0x1) == 0) {
                                let i_32;
                                if (type == 2) {
                                    i_32 = frame2TransformX - frame1TransformX & 0x3FFF;
                                    let i_33 = frame2TransformY - frame1TransformY & 0x3FFF;
                                    let i_34 = frame2TransformZ - frame1TransformZ & 0x3FFF;
                                    if (i_32 >= 8192)
                                        i_32 -= 16384;
    
                                    if (i_33 >= 8192)
                                        i_33 -= 16384;
    
                                    if (i_34 >= 8192)
                                        i_34 -= 16384;
    
                                    x = frame1TransformX + i_32 * i_4 / i_5 & 0x3FFF;
                                    y = frame1TransformY + i_33 * i_4 / i_5 & 0x3FFF;
                                    z = frame1TransformZ + i_34 * i_4 / i_5 & 0x3FFF;
                                } else if (type == 7) {
                                    i_32 = frame2TransformX - frame1TransformX & 0x3F;
                                    if (i_32 >= 32)
                                        i_32 -= 64;
    
                                    x = frame1TransformX + i_32 * i_4 / i_5 & 0x3F;
                                    y = frame1TransformY + (frame2TransformY - frame1TransformY) * i_4 / i_5;
                                    z = frame1TransformZ + (frame2TransformZ - frame1TransformZ) * i_4 / i_5;
                                } else if (type == 9) {
                                    i_32 = frame2TransformX - frame1TransformX & 0x3FFF;
                                    if (i_32 >= 8192)
                                        i_32 -= 16384;
    
                                    x = frame1TransformX + i_32 * i_4 / i_5 & 0x3FFF;
                                    z = 0;
                                    y = 0;
                                } else {
                                    x = frame1TransformX + (frame2TransformX - frame1TransformX) * i_4 / i_5;
                                    y = frame1TransformY + (frame2TransformY - frame1TransformY) * i_4 / i_5;
                                    z = frame1TransformZ + (frame2TransformZ - frame1TransformZ) * i_4 / i_5;
                                }
                            } else {
                                x = frame1TransformX;
                                y = frame1TransformY;
                                z = frame1TransformZ;
                            }
    
                            if (frame1Skip != -1)
                                this.transform(0, frameBase.Labels[frame1Skip], 0, 0, 0, i_6, bool_9, modelIndex & frameBase.AnIntArray7561[frame1Skip], ints_11);
                            else if (frame2Skip != -1)
                                this.transform(0, frameBase.Labels[frame2Skip], 0, 0, 0, i_6, bool_9, modelIndex & frameBase.AnIntArray7561[frame2Skip], ints_11);
    
                            this.transform(type, frameBase.Labels[index], x, y, z, i_6, bool_9, modelIndex & frameBase.AnIntArray7561[index], ints_11);
                        }
                    }
                }
            } else {
                for (let i = 0; i < frame1.TransformationCount; i++) {
                    let index = frame1.TransformationIndices[i];
                    if (bools_7 == null || bools_7[index] == bool_8 || frameBase.TransformationTypes[index] == 0) {
                        let skip = frame1.SkippedReferences[i];
                        if (skip != -1)
                            this.transform(0, frameBase.Labels[skip], 0, 0, 0, i_6, bool_9, modelIndex & frameBase.AnIntArray7561[skip], ints_11);
    
                        this.transform(frameBase.TransformationTypes[index], frameBase.Labels[index], frame1.TransformationX[i], frame1.TransformationY[i], frame1.TransformationZ[i], i_6, bool_9, modelIndex & frameBase.AnIntArray7561[index], ints_11);
                    }
                }
            }
        }
    
        this.transform = function(type, labels, transformX, transformY, transformZ, i_6, bool_7, i_8, ints_9) {
            let transformedX = transformX;
            let transformedZ = transformZ;
            let buffer;
            if (i_6 == 1) {
                if (type == 0 || type == 1) {
                    buffer = -transformedX;
                    transformedX = transformedZ;
                    transformedZ = buffer;
                } else if (type == 2) {
                    buffer = transformedX;
                    transformedX = -transformedZ & 0x3FFF;
                    transformedZ = buffer & 0x3FFF;
                } else if (type == 3) {
                    buffer = transformedX;
                    transformedX = transformedZ;
                    transformedZ = buffer;
                }
            } else if (i_6 == 2) {
                if (type == 0 || type == 1) {
                    transformedX = -transformedX;
                    transformedZ = -transformedZ;
                } else if (type == 2) {
                    transformedX = -transformedX & 0x3FFF;
                    transformedZ = -transformedZ & 0x3FFF;
                }
            } else if (i_6 == 3) {
                if (type == 0 || type == 1) {
                    buffer = transformedX;
                    transformedX = -transformedZ;
                    transformedZ = buffer;
                } else if (type == 2) {
                    buffer = transformedY;
                    transformedX = transformedZ & 0x3FFF;
                    transformedZ = -buffer & 0x3FFF;
                } else if (type == 3) {
                    buffer = transformedX;
                    transformedX = transformedZ;
                    transformedZ = buffer;
                }
            }
    
            if (i_8 != 65535)
                this.transformWithExtra();
            else
                this.finishTransform(type, labels, transformedX, transformY, transformedZ, i_6, bool_7);
        }
    
        this.transformWithExtra = function() {
            console.error('TRANSFORMED WITH EXTRA!!!! CODY!!!!');
        }
    
        this.finishTransform = function(type, labels, transformedX, transformedY, transformedZ, i_6, bool_7) {
            let labelCount = labels.length;
            if (type == 0) {
                transformedX <<= 4;
                transformedY <<= 4;
                transformedZ <<= 4;
                if (this.aBool8589 == false) {
                    for (let i = 0; i < this.vertexCount; i++) {
                        this.vertexX[i] <<= 4;
                        this.vertexY[i] <<= 4;
                        this.vertexZ[i] <<= 4;
                    }
    
                    this.aBool8589 = true;
                }
    
                let transformed = 0;
                this.xOffset = 0;
                this.yOffset = 0;
                this.zOffset = 0;
    
                for (let i = 0; i < labelCount; i++) {
                    let label = labels[i];
                    if (label < this.bones.length) {
                        let bones = this.bones[label];
                        for (let j = 0; j < bones.length; j++) {
                            let bone = bones[j];
                            this.xOffset += this.vertexX[bone];
                            this.yOffset += this.vertexY[bone];
                            this.zOffset += this.vertexZ[bone];
                            transformed++;
                        }
                    }
                }
    
                if (transformed > 0) {
                    this.xOffset = transformedX + this.xOffset / transformed;
                    this.yOffset = this.yOffset / transformed + transformedY;
                    this.zOffset = transformedZ + this.zOffset / transformed;
                } else {
                    this.xOffset = transformedX;
                    this.yOffset = transformedY;
                    this.zOffset = transformedZ;
                }
            } else if (type == 1) {
                transformedX <<= 4;
                transformedY <<= 4;
                transformedZ <<= 4;
                if (this.aBool8589 == false) {
                    for (let i = 0; i < this.vertexCount; i++) {
                        this.vertexX[i] <<= 4;
                        this.vertexY[i] <<= 4;
                        this.vertexZ[i] <<= 4;
                    }
    
                    this.aBool8589 = true;
                }
    
                for (let i = 0; i < labelCount; i++) {
                    let label = labels[i];
                    if (label < this.bones.length) {
                        let bones = this.bones[label];
                        for (let j = 0; j < bones.length; j++) {
                            let bone = bones[j];
                            this.vertexX[bone] += transformedX;
                            this.vertexY[bone] += transformedY;
                            this.vertexZ[bone] += transformedZ;
                        }
                    }
                }
            } else if (type == 2) {
                for (let i = 0; i < labelCount; i++) {
                    let label = labels[i];
                    if (label < this.bones.length) {
                        let bones = this.bones[label];
                        if ((i_6 & 0x1) == 0) {
                            for (let j = 0; j < bones.length; j++) {
                                let bone = bones[j];
                                this.vertexX[bone] -= this.xOffset;
                                this.vertexY[bone] -= this.yOffset;
                                this.vertexZ[bone] -= this.zOffset;
    
                                if (transformedZ != 0) {
                                    let sine = this.trig.getSine(transformedZ);
                                    let cosine = this.trig.getCosine(transformedZ);
                                    let newX = sine * this.vertexY[bone] + cosine * this.vertexX[bone] + 16383 >> 14;
                                    this.vertexY[bone] = cosine * this.vertexY[bone] - sine * this.vertexX[bone] + 16383 >> 14;
                                    this.vertexX[bone] = newX;
                                }
    
                                if (transformedX != 0) {
                                    let sine = this.trig.getSine(transformedX);
                                    let cosine = this.trig.getCosine(transformedX);
                                    let newY = cosine * this.vertexY[bone] - sine * this.vertexZ[bone] + 16383 >> 14;
                                    this.vertexZ[bone] = sine * this.vertexY[bone] + cosine * this.vertexZ[bone] + 16383 >> 14;
                                    this.vertexY[bone] = newY;
                                }
    
                                if (transformedY != 0) {
                                    let sine = this.trig.getSine(transformedY);
                                    let cosine = this.trig.getCosine(transformedY);
                                    let x = sine * this.vertexZ[bone] + cosine * this.vertexX[bone] + 16383 >> 14;
                                    this.vertexZ[bone] = cosine * this.vertexZ[bone] - sine * this.vertexX[bone] + 16383 >> 14;
                                    this.vertexX[bone] = x;
                                }
    
                                this.vertexX[bone] += this.xOffset;
                                this.vertexY[bone] += this.yOffset;
                                this.vertexZ[bone] += this.zOffset;
    
                            }
                        } else {
                            for (let j = 0; j < bones.length; j++) {
                                let bone = bones[j];
                                this.vertexX[bone] -= this.xOffset;
                                this.vertexY[bone] -= this.yOffset;
                                this.vertexZ[bone] -= this.zOffset;
    
                                if (transformedX != 0) {
                                    let sine = this.trig.getSine(transformedX);
                                    let cosine = this.trig.getCosine(transformedX);
                                    this.vertexZ[bone] = sine * this.vertexY[bone] + cosine * this.vertexZ[bone] + 16383 >> 14;
                                    this.vertexY[bone] = cosine * this.vertexY[bone] - sine * this.vertexZ[bone] + 16383 >> 14;
                                }
    
                                if (transformedZ != 0) {
                                    let sine = this.trig.getSine(transformedZ);
                                    let cosine = this.trig.getCosine(transformedZ);
                                    this.vertexY[bone] = cosine * this.vertexY[bone] - sine * this.vertexX[bone] + 16383 >> 14;
                                    this.vertexX[bone] = sine * this.vertexY[bone] + cosine * this.vertexX[bone] + 16383 >> 14;
                                }
    
                                if (transformedY != 0) {
                                    let sine = this.trig.getSine(transformedY);
                                    let cosine = this.trig.getCosine(transformedY);
                                    this.vertexZ[bone] = cosine * this.vertexZ[bone] - sine * this.vertexX[bone] + 16383 >> 14;
                                    this.vertexX[bone] = sine * this.vertexZ[bone] + cosine * this.vertexX[bone] + 16383 >> 14;
                                }
    
                                this.vertexX[bone] += this.xOffset;
                                this.vertexY[bone] += this.yOffset;
                                this.vertexZ[bone] += this.zOffset;
                            }
                        }
                    }
                }
            } else {
                console.error('UNHANDLED TYPE: ' + type);
            }
        }
    
    }
    Code:
    var FrameManager = FrameManager || {};
    
    FrameManager.FrameManager = function FrameManager() {
    
        this.frameLoaded = false;
    
        this.sets = [];
        this.flag = 0;
    
        this.getFrameSet = async function(id) {
            if (this.sets[id]) return this.sets[id];
            let set = await Promise.resolve($.post('/animations/sets/' + id, {}));
            let data = parseJSON(set);
            this.sets[id] = JSON.parse(data.set);
            return this.sets[id];
        }
    
        this.setupAnimationFrame = async function(defs, frame1Index, frame2Index, frames) {
            if (this.frameLoaded) return true;
            if (frame1Index >= frames.length)
                return false;
            this.frame1Id = frames[frame1Index];
            try {
                this.frameSet1 = await this.getFrameSet(this.frame1Id >> 16);
            } catch (error) {
                console.error(error);
                return false;
            }
            this.frame1Id &= 0xFFFF;
            if (this.frameSet1 == null) return false;
            if (defs.Tweened && frame2Index != -1 && frame2Index < frames.length) {
                this.frame2Id = frames[frame2Index];
                try {
                    this.frameSet2 = await this.getFrameSet(this.frame2Id >> 16);
                    this.frame2Id &= 0xFFFF;
                } catch (error) {
                    console.error(error);
                }
            }
            if (defs.ABool5923)
                this.flag |= 0x200;
    
            if (this.frameSet1.Frames[this.frame1Id].ModifiesColour)
                this.flag |= 0x80;
            if (this.frameSet1.Frames[this.frame1Id].ModifiesAlpha)
                this.flag |= 0x100;
            if (this.frameSet1.Frames[this.frame1Id].ABool988)
                this.flag |= 0x400;
    
            if (this.frameSet2 != null) {
    
                if (this.frameSet2.Frames[this.frame1Id].ModifiesColour)
                    this.flag |= 0x80;
                if (this.frameSet2.Frames[this.frame1Id].ModifiesAlpha)
                    this.flag |= 0x100;
                if (this.frameSet2.Frames[this.frame1Id].ABool988)
                    this.flag |= 0x400;
    
            }
    
            this.flag |= 0x20;
            this.frameLoaded = true;
            return true;
        }
    
        this.resetFrames = function() {
            this.frameLoaded = false;
            this.flag = 0;
            this.frameSet1 = null;
            this.frameSet2 = null;
        }
    
    }
    Code:
    var Trig = Trig || {};
    
    Trig.Trig = function Trig() {
    
        let SINE = Array(16384);
        let COSINE = Array(16384);
    
        this.init = function() {
            let step = 3.834951969714103E-4;
    
            for (let i = 0; i < 16384; i++) {
                SINE[i] = 16384.0 * Math.sin(i * step);
                COSINE[i] = 16384.0 * Math.cos(i * step);
            }
        }
    
        this.getSine = function(i) {
            return SINE[i];
        }
    
        this.getCosine = function(i) {
            return COSINE[i];
        }
    
        this.init();
    
    }
    Reply With Quote  
     

  7. #6  
    Registered Member
    Join Date
    Jan 2021
    Posts
    1
    Thanks given
    0
    Thanks received
    0
    Rep Power
    0
    Neat stuff!
    Reply With Quote  
     

  8. #7  
    *breaks walking*

    Cody_'s Avatar
    Join Date
    Dec 2010
    Posts
    721
    Thanks given
    204
    Thanks received
    189
    Discord
    View profile
    Rep Power
    267
    Having a hard time with material/textures. I have textures loading to a png, but if anyone can shoot me a message with some advice on how rs2 maps the sprite onto the model, I'd be very grateful.

    Taking a break from that, i've been working on spot animations (graphics):



    There's a small issue with some models disappearing at points during the animation. (As shown by end of first gif)
    Once I've figured that out, and tested with more, i'll update the post with the info.

    Also, the gif is low quality, but the animations are rendering at 50fps.

    For those wondering btw: they're called spot animations, because a 'graphic' is really a model that's rendered onto a certain tile, and an animation is played on that model.
    So, it's just an animation playing on a certain tile.

    Still can't edit main post for some reason. I've submitted a report about it.

    Edit: apologies. Still having some issues with fixing the disappearing frames.
    Seems to be something I added whilst adding spot animations, as the ags animation didn't use to disappear at random times, but does now.

    I'll figure it out, but might be another day before I post it. Sorry.
    Reply With Quote  
     

  9. #8  
    Registered Member
    Join Date
    Sep 2012
    Age
    21
    Posts
    47
    Thanks given
    4
    Thanks received
    2
    Rep Power
    11
    Quote Originally Posted by Cody_ View Post
    Having a hard time with material/textures. I have textures loading to a png, but if anyone can shoot me a message with some advice on how rs2 maps the sprite onto the model, I'd be very grateful.

    Taking a break from that, i've been working on spot animations (graphics):



    There's a small issue with some models disappearing at points during the animation. (As shown by end of first gif)
    Once I've figured that out, and tested with more, i'll update the post with the info.

    Also, the gif is low quality, but the animations are rendering at 50fps.

    For those wondering btw: they're called spot animations, because a 'graphic' is really a model that's rendered onto a certain tile, and an animation is played on that model.
    So, it's just an animation playing on a certain tile.

    Still can't edit main post for some reason. I've submitted a report about it.

    Edit: apologies. Still having some issues with fixing the disappearing frames.
    Seems to be something I added whilst adding spot animations, as the ags animation didn't use to disappear at random times, but does now.

    I'll figure it out, but might be another day before I post it. Sorry.
    Can this be modified to be used for 317 models? Im pretty familiar with three.js, from here you could create a model / animation editor. found this pretty interesting
    Reply With Quote  
     

  10. #9  
    *breaks walking*

    Cody_'s Avatar
    Join Date
    Dec 2010
    Posts
    721
    Thanks given
    204
    Thanks received
    189
    Discord
    View profile
    Rep Power
    267
    Quote Originally Posted by smiles down View Post
    Can this be modified to be used for 317 models? Im pretty familiar with three.js, from here you could create a model / animation editor. found this pretty interesting
    The three.js code shouldn't need too much modifying to be honest, (for rendering the model, animations will need some decent modifying) you would need to modify everything server sided to use the 317 model header though. (Add another decode method within RSMesh class)
    I don't know much about 317, but I think they are fairly similar. You'd get more help in the 'RS2 Client' section with this problem. Link them this thread and someone familiar with 317s should be able to help you out.

    OT: I've figured out the disappearing bit, and I now have spot animations working as well.



    Kevy got back to me on the editing issue, seems there might be just too much code. So I'll be uploading the project to github as a standalone demo, and I will just edit these posts and include a link to the github when I'm finished.
    Reply With Quote  
     

  11. #10  
    Contributor


    Join Date
    Dec 2009
    Posts
    771
    Thanks given
    357
    Thanks received
    432
    Discord
    View profile
    Rep Power
    880
    Quote Originally Posted by Cody_ View Post
    Having a hard time with material/textures. I have textures loading to a png, but if anyone can shoot me a message with some advice on how rs2 maps the sprite onto the model, I'd be very grateful.

    Taking a break from that, i've been working on spot animations (graphics):



    There's a small issue with some models disappearing at points during the animation. (As shown by end of first gif)
    Once I've figured that out, and tested with more, i'll update the post with the info.

    Also, the gif is low quality, but the animations are rendering at 50fps.

    For those wondering btw: they're called spot animations, because a 'graphic' is really a model that's rendered onto a certain tile, and an animation is played on that model.
    So, it's just an animation playing on a certain tile.

    Still can't edit main post for some reason. I've submitted a report about it.

    Edit: apologies. Still having some issues with fixing the disappearing frames.
    Seems to be something I added whilst adding spot animations, as the ags animation didn't use to disappear at random times, but does now.

    I'll figure it out, but might be another day before I post it. Sorry.
    I've implemented threejs model rendering with textures in an Electron app: https://github.com/rune-js/toolkit/b...service.ts#L83



    Have fun ripping
    link removed
    Reply With Quote  
     

  12. Thankful users:



Thread Information
Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)


User Tag List

Similar Threads

  1. Replies: 2
    Last Post: 12-01-2011, 02:18 PM
  2. please help me with adding models to a PI
    By yuioplok in forum Help
    Replies: 4
    Last Post: 10-06-2011, 06:19 AM
  3. Help with adding models to 562
    By Mythic in forum Help
    Replies: 1
    Last Post: 11-10-2010, 06:32 AM
  4. Rendering items to 525 character models
    By Diverse Reality in forum Help
    Replies: 3
    Last Post: 10-26-2010, 05:16 AM
  5. How to luanch a website with your defualt browser
    By Shamon King in forum Tutorials
    Replies: 2
    Last Post: 02-14-2008, 04:43 AM
Posting Permissions
  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •