Thread: Model Encoder

Results 1 to 5 of 5
  1. #1 Model Encoder 
    I heal clients


    Join Date
    Apr 2013
    Posts
    680
    Thanks given
    65
    Thanks received
    239
    Rep Power
    108
    Don't bug me about it, if you don't like it, write better.

    Supports 317-742 decoding, 742-alike encoding.

    Mesh.java
    Code:
    package com.wycody.engine.media.mesh;
    
    
    import com.wycody.engine.media.particle.*;
    
    
    /**
     * Created at: Apr 11, 2017 1:04:42 AM
     * 
     * @author Walied-Yassen
     */
    public abstract class Mesh {
    
    
        /**
         * The default mesh version.
         */
        protected static final int DEFAULT_VERSION = 12;
    
    
        /**
         * The model format version. (default is 12)
         */
        protected int version;
    
    
        /**
         * The amount of vertices stored within this mesh.
         */
        protected int numVertices;
    
    
        /**
         * The amount of faces stored within this mesh.
         */
        protected int numFaces;
    
    
        /**
         * The amount of textured faces stored within this mesh.
         */
        protected int numTextures;
    
    
        /**
         * The model itself priority.
         */
        protected byte priority;
    
    
        /**
         * The biggest face index.
         */
        protected int maxIndex;
    
    
        /**
         * The vertices x position.
         */
        protected int[] verticesX;
    
    
        /**
         * The vertices y position.
         */
        protected int[] verticesY;
    
    
        /**
         * The vertices z position.
         */
        protected int[] verticesZ;
    
    
        /**
         * The vertex skins.
         */
        protected int[] vertexSkins;
    
    
        /**
         * The face point A vertex indices.
         */
        protected short[] faceIndicesA;
    
    
        /**
         * The face point B vertex indices.
         */
        protected short[] faceIndicesB;
    
    
        /**
         * The face point C vertex indices.
         */
        protected short[] faceIndicesC;
    
    
        /**
         * The face types.
         */
        protected byte[] faceTypes;
    
    
        /**
         * The face priorities.
         */
        protected byte[] facePriorities;
    
    
        /**
         * The face alphas.
         */
        protected byte[] faceAlphas;
    
    
        /**
         * The face texture indices.
         */
        protected byte[] faceTextures;
    
    
        /**
         * The face colors.
         */
        protected short[] faceColors;
    
    
        /**
         * The face materials.
         */
        protected short[] faceMaterials;
    
    
        /**
         * The face skins.
         */
        protected int[] faceSkins;
    
    
        /**
         * The face mappings.
         */
        protected byte[] faceMappings;
    
    
        /**
         * The face texture mapping P value.
         */
        protected short[] textureMappingP;
    
    
        /**
         * The face texture mapping M value.
         */
        protected short[] textureMappingM;
    
    
        /**
         * The face texture mapping N value.
         */
        protected short[] textureMappingN;
    
    
        /**
         * The face texture scale x.
         */
        protected int[] textureScaleX;
    
    
        /**
         * The face texture scale y.
         */
        protected int[] textureScaleY;
    
    
        /**
         * The face texture scale y.
         */
        protected int[] textureScaleZ;
    
    
        /**
         * The face texture rotation.
         */
        protected byte[] textureRotation;
    
    
        /**
         * The face texture direction.
         */
        protected byte[] textureDirection;
    
    
        /**
         * The face texture speed.
         */
        protected int[] textureSpeed;
    
    
        /**
         * The face texture x translations.
         */
        protected int[] textureTransV;
    
    
        /**
         * The face texture y translations.
         */
        protected int[] textureTransU;
    
    
        /**
         * The particle emitters.
         */
        protected EmissiveTriangle[] emitters;
    
    
        /**
         * The particle effectors.
         */
        protected EffectiveVertex[] effectors;
    
    
        /**
         * The billboards.
         */
        protected FaceBillboard[] billboards;
    
    
        /**
         * Constructs a new {@link Mesh} object instance.
         * 
         * @param data
         *            the raw mesh file data.
         */
        public Mesh(byte[] data) {
            maxIndex = 0;
            numFaces = 0;
            priority = (byte) 0;
            numTextures = 0;
            decode(data);
        }
    
    
        /**
         * Constructs a new {@link Mesh} object instance.
         * 
         * @param numVertices
         *            the amount of vertices within this mesh.
         * @param numFaces
         *            the amount of faces within this mesh.
         * @param numTexturedFaces
         *            the amount of textured faces within this mesh.
         */
        public Mesh(int numVertices, int numFaces, int numTexturedFaces) {
            version = DEFAULT_VERSION;
            verticesX = new int[numVertices];
            verticesY = new int[numVertices];
            verticesZ = new int[numVertices];
            vertexSkins = new int[numVertices];
            faceIndicesA = new short[numFaces];
            faceIndicesB = new short[numFaces];
            faceIndicesC = new short[numFaces];
            faceTypes = new byte[numFaces];
            facePriorities = new byte[numFaces];
            faceAlphas = new byte[numFaces];
            faceTextures = new byte[numFaces];
            faceColors = new short[numFaces];
            faceMaterials = new short[numFaces];
            faceSkins = new int[numFaces];
            if (numTexturedFaces > 0) {
                faceMappings = new byte[numTexturedFaces];
                textureMappingP = new short[numTexturedFaces];
                textureMappingM = new short[numTexturedFaces];
                textureMappingN = new short[numTexturedFaces];
                textureScaleX = new int[numTexturedFaces];
                textureScaleY = new int[numTexturedFaces];
                textureScaleZ = new int[numTexturedFaces];
                textureRotation = new byte[numTexturedFaces];
                textureDirection = new byte[numTexturedFaces];
                textureSpeed = new int[numTexturedFaces];
                textureTransU = new int[numTexturedFaces];
                textureTransV = new int[numTexturedFaces];
            }
        }
    
    
        /**
         * Deserializes this {@link Mesh} instance from the specified {@code data}
         * buffer.
         * 
         * @param data
         *            the model data.
         */
        public abstract void decode(byte[] data);
    
    
        /**
         * Serializes this {@link Mesh} instance into a {@code byte} array.
         * 
         * @return the serialized {@code byte} array.
         */
        public abstract byte[] encode();
    
    
        /**
         * Adds a new vertex to the mesh.
         * 
         * @param x
         *            the vertex x position.
         * @param y
         *            the vertex y position.
         * @param z
         *            the vertex z position.
         * @return the vertex index.
         */
        public int addVertex(int x, int y, int z) {
            for (int index = 0; index < numVertices; index++) {
                if (verticesX[index] == x && verticesY[index] == y && verticesZ[index] == z) {
                    return index;
                }
            }
            verticesX[numVertices] = x;
            verticesY[numVertices] = y;
            verticesZ[numVertices] = z;
            return numVertices++;
        }
    
    
        /**
         * Adds a new face to the mesh.
         * 
         * @param a
         *            the face point A index.
         * @param b
         *            the face point B index.
         * @param c
         *            the face point C index.
         * @param color
         *            the face color.
         * @param alpha
         *            the face alpha.
         * @return the face index.
         */
        public int addFace(int a, int b, int c, short color, byte alpha) {
            faceIndicesA[numFaces] = (short) a;
            faceIndicesB[numFaces] = (short) b;
            faceIndicesC[numFaces] = (short) c;
            faceColors[numFaces] = color;
            faceAlphas[numFaces] = alpha;
            return numFaces++;
        }
    
    
        /**
         * Gets the format version.
         * 
         * @return the format version.
         */
        public int getVersion() {
            return version;
        }
    
    
        /**
         * Sets the format version.
         * 
         * @param format
         *            the new format version.
         */
        public void setFormat(int format) {
            version = format;
        }
    
    
        /**
         * Gets the amount of vertices we have within this model.
         * 
         * @return the amount of vertices.
         */
        public int getNumVertices() {
            return numVertices;
        }
    
    
        /**
         * Sets the amount of vertices within this model.
         * 
         * @param numVertices
         *            the amount of vertices within this model.
         */
        public void setNumVertices(int numVertices) {
            this.numVertices = numVertices;
        }
    
    
        /**
         * Gets the amount of faces within this mesh.
         * 
         * @return the numFaces the amount of faces within this mesh.
         */
        public int getNumFaces() {
            return numFaces;
        }
    
    
        /**
         * Sets the amount of faces within this mesh.
         * 
         * @param numFaces
         *            the amount of faces to set.
         */
        public void setNumFaces(int numFaces) {
            this.numFaces = numFaces;
        }
    
    
        /**
         * Gets the amount of textures faces we have within this mesh.
         * 
         * @return the amount of textures faces we have within this mesh.
         */
        public int getNumTextures() {
            return numTextures;
        }
    
    
        /**
         * Sets the amount of textures faces within this mesh.
         * 
         * @param numTexturedFaces
         *            the amount of textures faces to set.
         */
        public void setNumTextures(int numTexturedFaces) {
            this.numTextures = numTexturedFaces;
        }
    
    
        /**
         * Gets the model priority.
         * 
         * @return the model priority.
         */
        public byte getPriority() {
            return priority;
        }
    
    
        /**
         * Sets the model priority.
         * 
         * @param priority
         *            the model priority to set.
         */
        public void setPriority(byte priority) {
            this.priority = priority;
        }
    
    
        /**
         * Gets the biggest face index.
         * 
         * @return the biggest face index.
         */
        public int getMaxIndex() {
            return maxIndex;
        }
    
    
        /**
         * Sets the biggest face index.
         * 
         * @param maxIndex
         *            the new biggest face index.
         */
        public void setMaxIndex(int maxIndex) {
            this.maxIndex = maxIndex;
        }
    
    
        /**
         * Gets the vertices x position.
         * 
         * @return the vertices x position.
         */
        public int[] getVerticesX() {
            return verticesX;
        }
    
    
        /**
         * Sets the vertices x position.
         * 
         * @param verticesX
         *            the vertices x position.
         */
        public void setVerticesX(int[] verticesX) {
            this.verticesX = verticesX;
        }
    
    
        /**
         * Gets the vertices y position.
         * 
         * @return the vertices y position.
         */
        public int[] getVerticesY() {
            return verticesY;
        }
    
    
        /**
         * Sets the vertices y position.
         * 
         * @param verticesY
         *            the vertices y position.
         */
        public void setVerticesY(int[] verticesY) {
            this.verticesY = verticesY;
        }
    
    
        /**
         * Gets the vertices z position.
         * 
         * @return the vertices z position.
         */
        public int[] getVerticesZ() {
            return verticesZ;
        }
    
    
        /**
         * Sets the vertices z position.
         * 
         * @param verticesZ
         *            the vertices z position.
         */
        public void setVerticesZ(int[] verticesZ) {
            this.verticesZ = verticesZ;
        }
    
    
        /**
         * Gets the vertex skins.
         * 
         * @return the vertex skins.
         */
        public int[] getVertexSkins() {
            return vertexSkins;
        }
    
    
        /**
         * Sets the vertex skins.
         * 
         * @param vertexSkins
         *            the new vertex skins to set.
         */
        public void setVertexSkins(int[] vertexSkins) {
            this.vertexSkins = vertexSkins;
        }
    
    
        /**
         * Gets the face point A vertex indices.
         * 
         * @return the face point A vertex indices.
         */
        public short[] getFaceIndicesA() {
            return faceIndicesA;
        }
    
    
        /**
         * Sets the face point A vertex indices.
         * 
         * @param faceIndicesA
         *            the face point A vertex indices.
         */
        public void setFaceIndicesA(short[] faceIndicesA) {
            this.faceIndicesA = faceIndicesA;
        }
    
    
        /**
         * Gets the face point B vertex indices.
         * 
         * @return the face point BA vertex indices.
         */
        public short[] getFaceIndicesB() {
            return faceIndicesB;
        }
    
    
        /**
         * Sets the face point B vertex indices.
         * 
         * @param faceIndicesA
         *            the face point B vertex indices.
         */
        public void setFaceIndicesB(short[] faceIndicesB) {
            this.faceIndicesB = faceIndicesB;
        }
    
    
        /**
         * Gets the face point C vertex indices.
         * 
         * @return the face point A vertex indices.
         */
        public short[] getFaceIndicesC() {
            return faceIndicesC;
        }
    
    
        /**
         * Sets the face point C vertex indices.
         * 
         * @param faceIndicesA
         *            the face point C vertex indices.
         */
        public void setFaceIndicesC(short[] faceIndicesC) {
            this.faceIndicesC = faceIndicesC;
        }
    
    
        /**
         * Gets the face types.
         * 
         * @return the face types.
         */
        public byte[] getFaceTypes() {
            return faceTypes;
        }
    
    
        /**
         * Sets the face types.
         * 
         * @param faceTypes
         *            the face types.
         */
        public void setFaceTypes(byte[] faceTypes) {
            this.faceTypes = faceTypes;
        }
    
    
        /**
         * Gets the face priorities.
         * 
         * @return the face priorities.
         */
        public byte[] getFacePriorities() {
            return facePriorities;
        }
    
    
        /**
         * Sets the face priorities.
         * 
         * @param facePriorities
         *            the new face priorities.
         */
        public void setFacePriorities(byte[] facePriorities) {
            this.facePriorities = facePriorities;
        }
    
    
        /**
         * Gets the face alpha values.
         * 
         * @return the face alpha values.
         */
        public byte[] getFaceAlphas() {
            return faceAlphas;
        }
    
    
        /**
         * Sets the face alpha values.
         * 
         * @param alphas
         *            the face alpha values.
         */
        public void setFaceAlphas(byte[] alphas) {
            faceAlphas = alphas;
        }
    
    
        /**
         * Gets the face textures.
         * 
         * @return the face textures.
         */
        public byte[] getFaceTextures() {
            return faceTextures;
        }
    
    
        /**
         * Sets the face textures.
         * 
         * @param faceTextures
         *            the new face textures to set.
         */
        public void setFaceTextures(byte[] faceTextures) {
            this.faceTextures = faceTextures;
        }
    
    
        /**
         * Gets the face colors.
         * 
         * @return the face colors.
         */
        public short[] getFaceColors() {
            return faceColors;
        }
    
    
        /**
         * Sets the face colors.
         * 
         * @param colors
         *            the new face colors to set.
         */
        public void setFaceColors(short[] colors) {
            faceColors = colors;
        }
    
    
        /**
         * Gets the face materials.
         * 
         * @return the face materials.
         */
        public short[] getFaceMaterials() {
            return faceMaterials;
        }
    
    
        /**
         * Sets the face materials.
         * 
         * @param faceMaterials
         *            the new face materials.
         */
        public void setFaceMaterials(short[] faceMaterials) {
            this.faceMaterials = faceMaterials;
        }
    
    
        /**
         * Gets the face skins.
         * 
         * @return the face skins.
         */
        public int[] getFaceSkins() {
            return faceSkins;
        }
    
    
        /**
         * Sets the face skins.
         * 
         * @param faceSkins
         *            the new face skins to set.
         */
        public void setFaceSkins(int[] faceSkins) {
            this.faceSkins = faceSkins;
        }
    
    
        /**
         * Gets the face mappings.
         * 
         * @return the face mappings.
         */
        public byte[] getFaceMappings() {
            return faceMappings;
        }
    
    
        /**
         * Sets the face mappings.
         * 
         * @param faceMappings
         *            the face mappings.
         */
        public void setFaceMappings(byte[] faceMappings) {
            this.faceMappings = faceMappings;
        }
    
    
        /**
         * Gets the face texture mapping P values.
         * 
         * @return the face texture mapping P values.
         */
        public short[] getTextureMappingP() {
            return textureMappingP;
        }
    
    
        /**
         * Sets the face texture mapping P values.
         * 
         * @param faceTextureP
         *            the new face texture mapping P values.
         */
        public void setTextureMappingP(short[] faceTextureP) {
            textureMappingP = faceTextureP;
        }
    
    
        /**
         * Gets the face texture mapping M values.
         * 
         * @return the face texture mapping M values.
         */
        public short[] getTextureMappingM() {
            return textureMappingM;
        }
    
    
        /**
         * Sets the face texture mapping M values.
         * 
         * @param textureMappingP
         *            the new face texture mapping M values.
         */
        public void setTextureMappingM(short[] faceTextureM) {
            textureMappingM = faceTextureM;
        }
    
    
        /**
         * Gets the face texture mapping N values.
         * 
         * @return the face texture mapping N values.
         */
        public short[] getTextureMappingN() {
            return textureMappingN;
        }
    
    
        /**
         * Sets the face texture mapping N values.
         * 
         * @param textureMappingP
         *            the new face texture mapping N values.
         */
        public void setTextureMappingN(short[] faceTextureN) {
            textureMappingN = faceTextureN;
        }
    
    
        /**
         * Gets the face texture scale down x multipliers.
         * 
         * @return the face texture scale down x multipliers.
         */
        public int[] getTextureScaleX() {
            return textureScaleX;
        }
    
    
        /**
         * Sets the face texture scale down x multipliers.
         * 
         * @param textureScaleX
         *            the new face texture scale down x multipliers.
         */
        public void setTextureScaleX(int[] textureScaleX) {
            this.textureScaleX = textureScaleX;
        }
    
    
        /**
         * Gets the face texture scale down y multipliers.
         * 
         * @return the face texture scale down y multipliers.
         */
        public int[] getTextureScaleY() {
            return textureScaleY;
        }
    
    
        /**
         * Sets the face texture scale down y multipliers.
         * 
         * @param textureScaleY
         *            the new face texture scale down y multiplies.
         */
        public void setTextureScaleY(int[] textureScaleY) {
            this.textureScaleY = textureScaleY;
        }
    
    
        /**
         * Gets the face texture scale down z multipliers.
         * 
         * @return the face texture scale down z multipliers.
         */
        public int[] getTextureScaleZ() {
            return textureScaleZ;
        }
    
    
        /**
         * Sets the face texture scale down z multipliers.
         * 
         * @param textureScaleY
         *            the new face texture scale down z multipliers.
         */
        public void setTextureScaleZ(int[] textureScaleZ) {
            this.textureScaleZ = textureScaleZ;
        }
    
    
        /**
         * Gets the face texture rotation values.
         * 
         * @return the textureRotation the face texture rotation values.
         */
        public byte[] getTextureRotation() {
            return textureRotation;
        }
    
    
        /**
         * Sets the face texture rotation values.
         * 
         * @param textureRotation
         *            the new face texture rotation values.
         */
        public void setTextureRotation(byte[] textureRotation) {
            this.textureRotation = textureRotation;
        }
    
    
        /**
         * Gets the face texture direction values.
         * 
         * @return the textureRotation the face texture direction values.
         */
        public byte[] getTextureDirection() {
            return textureDirection;
        }
    
    
        /**
         * Sets the face texture direction values.
         * 
         * @param textureRotation
         *            the new face texture direction values.
         */
        public void setTextureDirection(byte[] textureDirection) {
            this.textureDirection = textureDirection;
        }
    
    
        /**
         * Gets the face texture speed values.
         * 
         * @return the face texture speed values.
         */
        public int[] getTextureSpeed() {
            return textureSpeed;
        }
    
    
        /**
         * Sets the face texture speed values.
         * 
         * @param textureSpeed
         *            the new face texture speed values.
         */
        public void setTextureSpeed(int[] textureSpeed) {
            this.textureSpeed = textureSpeed;
        }
    
    
        /**
         * Gets the face texture x translations.
         * 
         * @return the face texture x translations.
         */
        public int[] getTextureTransX() {
            return textureTransV;
        }
    
    
        /**
         * Sets the face texture x translations.
         * 
         * @param textureTransX
         *            the new face texture x translations.
         */
        public void setTextureTransX(int[] textureTransX) {
            textureTransV = textureTransX;
        }
    
    
        /**
         * Gets the face texture x translations.
         * 
         * @return the face texture x translations.
         */
        public int[] getTextureTransY() {
            return textureTransU;
        }
    
    
        /**
         * Sets the face texture y translations.
         * 
         * @param textureTransV
         *            the new face texture y translations.
         */
        public void setTextureTransY(int[] textureTransY) {
            textureTransU = textureTransY;
        }
    
    
        /**
         * Gets the particle emitters.
         * 
         * @return the particle emitters.
         */
        public EmissiveTriangle[] getEmitters() {
            return emitters;
        }
    
    
        /**
         * Sets the particle emitters.
         * 
         * @param emitters
         *            the new particle emitters.
         */
        public void setEmitters(EmissiveTriangle[] emitters) {
            this.emitters = emitters;
        }
    
    
        /**
         * Gets the particle effectors.
         * 
         * @return the particle effectors.
         */
        public EffectiveVertex[] getEffectors() {
            return effectors;
        }
    
    
        /**
         * Sets the particle effectors.
         * 
         * @param emitters
         *            the new particle effectors.
         */
        public void setEffectors(EffectiveVertex[] effectors) {
            this.effectors = effectors;
        }
    
    
        /**
         * Gets the billboards.
         * 
         * @return the billboards.
         */
        public FaceBillboard[] getBillboards() {
            return billboards;
        }
    
    
        /**
         * Sets the billboards.
         * 
         * @param billboards
         *            the new billboards to set.
         */
        public void setBillboards(FaceBillboard[] billboards) {
            this.billboards = billboards;
        }
    
    
    }
    RsMesh
    Code:
    package com.wycody.engine.media.mesh;
    
    
    import com.wycody.core.bytepacking.*;
    import com.wycody.engine.media.particle.*;
    
    
    /**
     * Created at: Apr 15, 2017 5:43:53 PM
     * 
     * @author Walied-Yassen
     */
    public class RsMesh extends Mesh {
    
    
        /**
         * Constructs a new {@link RsMesh} object instance.
         * 
         * @param data
         *            the raw mesh file data.
         */
        public RsMesh(byte[] data) {
            super(data);
        }
    
    
        /**
         * Constructs a new {@link RsMesh} object instance.
         * 
         * @param numVertices
         *            the amount of vertices within this mesh.
         * @param numFaces
         *            the amount of faces within this mesh.
         * @param numTexturedFaces
         *            the amount of textures within this mesh.
         */
        public RsMesh(int numVertices, int numFaces, int numTextures) {
            super(numVertices, numFaces, numTextures);
        }
    
    
        /*
         * (non-Javadoc)
         * 
         * @see com.wycody.engine.media.model.Mesh#load(byte[])
         */
        @Override
        public void decode(byte[] data) {
            if (data[data.length - 1] == -1 && data[data.length - 2] == -1) {
                Buffer first = new FixedBuffer(data);
                Buffer second = new FixedBuffer(data);
                Buffer third = new FixedBuffer(data);
                Buffer fourth = new FixedBuffer(data);
                Buffer fifth = new FixedBuffer(data);
                Buffer sixth = new FixedBuffer(data);
                Buffer seventh = new FixedBuffer(data);
                first.setOffset(data.length - 23);
                numVertices = first.readUnsignedShort();
                numFaces = first.readUnsignedShort();
                numTextures = first.readUnsignedByte();
                int footerFlags = first.readUnsignedByte();
                boolean hasFaceTypes = (footerFlags & 0x1) == 1;
                boolean hasParticleEffects = (footerFlags & 0x2) == 2;
                boolean hasBillboards = (footerFlags & 0x4) == 4;
                boolean hasVersion = (footerFlags & 0x8) == 8;
                boolean hasExtendedVertexSkins = (footerFlags & 0x10) == 16;
                boolean hasExtendedTriangleSkins = (footerFlags & 0x20) == 32;
                boolean hasExtendedBillboards = (footerFlags & 0x40) == 64;
                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();
                int numVertexSkins;
                if (hasExtendedVertexSkins) {
                    numVertexSkins = first.readUnsignedShort();
                } else if (hasVertexSkins == 1) {
                    numVertexSkins = numVertices;
                } else {
                    numVertexSkins = 0;
                }
                int numFaceSkins;
                if (hasExtendedTriangleSkins) {
                    numFaceSkins = first.readUnsignedShort();
                } else if (hasFaceSkins == 1) {
                    numFaceSkins = numFaces;
                } else {
                    numFaceSkins = 0;
                }
                int simpleTextureFaceCount = 0;
                int complexTextureFaceCount = 0;
                int cubeTextureFaceCount = 0;
                if (numTextures > 0) {
                    faceMappings = new byte[numTextures];
                    first.setOffset(0);
                    for (int tri = 0; tri < numTextures; tri++) {
                        byte type = faceMappings[tri] = (byte) first.readByte();
                        if (type == 0) {
                            simpleTextureFaceCount++;
                        }
                        if (type >= 1 && type <= 3) {
                            complexTextureFaceCount++;
                        }
                        if (type == 2) {
                            cubeTextureFaceCount++;
                        }
                    }
                }
                int offset = numTextures;
                int vertexFlagsOffset = offset;
                offset += numVertices;
                int faceTypesOffset = offset;
                if (hasFaceTypes) {
                    offset += numFaces;
                }
                int facesCompressTypeOffset = offset;
                offset += numFaces;
                int facePrioritiesOffset = offset;
                if (modelPriority == 255) {
                    offset += numFaces;
                }
                int faceSkinsOffset = offset;
                offset += numFaceSkins;
                int vertexSkinsOffset = offset;
                offset += numVertexSkins;
                int faceAlphasOffset = offset;
                if (hasFaceAlpha == 1) {
                    offset += numFaces;
                }
                int faceIndicesOffset = offset;
                offset += faceIndices;
                int faceMaterialsOffset = offset;
                if (hasFaceTextures == 1) {
                    offset += numFaces * 2;
                }
                int faceTextureIndicesOffset = offset;
                offset += textureIndices;
                int faceColorsOffset = offset;
                offset += numFaces * 2;
                int vertexXOffsetOffset = offset;
                offset += modelVerticesX;
                int vertexYOffsetOffset = offset;
                offset += modelVerticesY;
                int vertexZOffsetOffset = offset;
                offset += modelVerticesZ;
                int simpleTexturesOffset = offset;
                offset += simpleTextureFaceCount * 6;
                int complexTexturesOffset = offset;
                offset += complexTextureFaceCount * 6;
                int textureBytes = 6;
                if (version == 14) {
                    textureBytes = 7;
                } else if (version >= 15) {
                    textureBytes = 9;
                }
                int texturesScaleOffset = offset;
                offset += complexTextureFaceCount * textureBytes;
                int texturesRotationOffset = offset;
                offset += complexTextureFaceCount;
                int texturesDirectionOffset = offset;
                offset += complexTextureFaceCount;
                int texturesTranslationOffset = offset;
                offset += complexTextureFaceCount + cubeTextureFaceCount * 2;
                int particleEffectsOffset = offset;
                verticesX = new int[numVertices];
                verticesY = new int[numVertices];
                verticesZ = new int[numVertices];
                faceIndicesA = new short[numFaces];
                faceIndicesB = new short[numFaces];
                faceIndicesC = new short[numFaces];
                if (hasVertexSkins == 1) {
                    vertexSkins = new int[numVertices];
                }
                if (hasFaceTypes) {
                    faceTypes = new byte[numFaces];
                }
                if (modelPriority == 255) {
                    facePriorities = new byte[numFaces];
                } else {
                    priority = (byte) modelPriority;
                }
                if (hasFaceAlpha == 1) {
                    faceAlphas = new byte[numFaces];
                }
                if (hasFaceSkins == 1) {
                    faceSkins = new int[numFaces];
                }
                if (hasFaceTextures == 1) {
                    faceMaterials = new short[numFaces];
                }
                if (hasFaceTextures == 1 && numTextures > 0) {
                    faceTextures = new byte[numFaces];
                }
                faceColors = new short[numFaces];
                if (numTextures > 0) {
                    textureMappingP = new short[numTextures];
                    textureMappingM = new short[numTextures];
                    textureMappingN = new short[numTextures];
                    if (complexTextureFaceCount > 0) {
                        textureScaleX = new int[complexTextureFaceCount];
                        textureScaleY = new int[complexTextureFaceCount];
                        textureScaleZ = new int[complexTextureFaceCount];
                        textureRotation = new byte[complexTextureFaceCount];
                        textureDirection = new byte[complexTextureFaceCount];
                        textureSpeed = new int[complexTextureFaceCount];
                    }
                    if (cubeTextureFaceCount > 0) {
                        textureTransU = new int[cubeTextureFaceCount];
                        textureTransV = new int[cubeTextureFaceCount];
                    }
                }
                first.setOffset(vertexFlagsOffset);
                second.setOffset(vertexXOffsetOffset);
                third.setOffset(vertexYOffsetOffset);
                fourth.setOffset(vertexZOffsetOffset);
                fifth.setOffset(vertexSkinsOffset);
                int baseX = 0;
                int baseY = 0;
                int baseZ = 0;
                for (int vertex = 0; vertex < numVertices; vertex++) {
                    int pflag = first.readUnsignedByte();
                    int xOffset = 0;
                    if ((pflag & 0x1) != 0) {
                        xOffset = second.readUnsignedSmart();
                    }
                    int yOffset = 0;
                    if ((pflag & 0x2) != 0) {
                        yOffset = third.readUnsignedSmart();
                    }
                    int zOffset = 0;
                    if ((pflag & 0x4) != 0) {
                        zOffset = fourth.readUnsignedSmart();
                    }
                    verticesX[vertex] = baseX + xOffset;
                    verticesY[vertex] = baseY + yOffset;
                    verticesZ[vertex] = baseZ + zOffset;
                    baseX = verticesX[vertex];
                    baseY = verticesY[vertex];
                    baseZ = verticesZ[vertex];
                    if (hasVertexSkins == 1) {
                        if (hasExtendedVertexSkins) {
                            vertexSkins[vertex] = fifth.readSmartNS();
                        } else {
                            vertexSkins[vertex] = fifth.readUnsignedByte();
                            if (vertexSkins[vertex] == 255) {
                                vertexSkins[vertex] = -1;
                            }
                        }
                    }
                }
                first.setOffset(faceColorsOffset);
                second.setOffset(faceTypesOffset);
                third.setOffset(facePrioritiesOffset);
                fourth.setOffset(faceAlphasOffset);
                fifth.setOffset(faceSkinsOffset);
                sixth.setOffset(faceMaterialsOffset);
                seventh.setOffset(faceTextureIndicesOffset);
                for (int face = 0; face < numFaces; face++) {
                    faceColors[face] = (short) first.readUnsignedShort();
                    if (hasFaceTypes) {
                        faceTypes[face] = (byte) second.readByte();
                    }
                    if (modelPriority == 255) {
                        facePriorities[face] = (byte) third.readByte();
                    }
                    if (hasFaceAlpha == 1) {
                        faceAlphas[face] = (byte) fourth.readByte();
                    }
                    if (hasFaceSkins == 1) {
                        if (hasExtendedTriangleSkins) {
                            faceSkins[face] = fifth.readSmartNS();
                        } else {
                            faceSkins[face] = fifth.readUnsignedByte();
                            if (faceSkins[face] == 255) {
                                faceSkins[face] = -1;
                            }
                        }
                    }
                    if (hasFaceTextures == 1) {
                        faceMaterials[face] = (short) (sixth.readUnsignedShort() - 1);
                    }
                    if (faceTextures != null) {
                        if (faceMaterials[face] != -1) {
                            faceTextures[face] = (byte) (seventh.readUnsignedByte() - 1);
                        } else {
                            faceTextures[face] = (byte) -1;
                        }
                    }
                }
                maxIndex = -1;
                first.setOffset(faceIndicesOffset);
                second.setOffset(facesCompressTypeOffset);
                decodeIndices(first, second);
                first.setOffset(simpleTexturesOffset);
                second.setOffset(complexTexturesOffset);
                third.setOffset(texturesScaleOffset);
                fourth.setOffset(texturesRotationOffset);
                fifth.setOffset(texturesDirectionOffset);
                sixth.setOffset(texturesTranslationOffset);
                decodeMapping(first, second, third, fourth, fifth, sixth);
                first.setOffset(particleEffectsOffset);
                if (hasParticleEffects) {
                    int numEmitters = first.readUnsignedByte();
                    if (numEmitters > 0) {
                        emitters = new EmissiveTriangle[numEmitters];
                        for (int index = 0; index < numEmitters; index++) {
                            int emitter = first.readUnsignedShort();
                            int face = first.readUnsignedShort();
                            byte pri;
                            if (modelPriority == 255) {
                                pri = facePriorities[face];
                            } else {
                                pri = (byte) modelPriority;
                            }
                            emitters[index] = new EmissiveTriangle(emitter, face, faceIndicesA[face], faceIndicesB[face], faceIndicesC[face], pri);
                        }
                    }
                    int numEffectors = first.readUnsignedByte();
                    if (numEffectors > 0) {
                        effectors = new EffectiveVertex[numEffectors];
                        for (int index = 0; index < numEffectors; index++) {
                            int effector = first.readUnsignedShort();
                            int vertex = first.readUnsignedShort();
                            effectors[index] = new EffectiveVertex(effector, vertex);
                        }
                    }
                }
                if (hasBillboards) {
                    int numBillboards = first.readUnsignedByte();
                    if (numBillboards > 0) {
                        billboards = new FaceBillboard[numBillboards];
                        for (int index = 0; index < numBillboards; index++) {
                            int id = first.readUnsignedShort();
                            int face = first.readUnsignedShort();
                            int skin;
                            if (hasExtendedBillboards) {
                                skin = first.readSmartNS();
                            } else {
                                skin = first.readUnsignedByte();
                                if (skin == 255) {
                                    skin = -1;
                                }
                            }
                            byte distance = (byte) first.readByte();
                            billboards[index] = new FaceBillboard(id, face, skin, distance);
                        }
                    }
                }
            } else {
                boolean usesFaceTypes = false;
                boolean usesMaterials = false;
                Buffer first = new FixedBuffer(data);
                Buffer second = new FixedBuffer(data);
                Buffer third = new FixedBuffer(data);
                Buffer fourth = new FixedBuffer(data);
                Buffer fifth = new FixedBuffer(data);
                first.setOffset(data.length - 18);
                numVertices = first.readUnsignedShort();
                numFaces = first.readUnsignedShort();
                numTextures = first.readUnsignedByte();
                int hasFaceTypes = first.readUnsignedByte();
                int modelPriority = first.readUnsignedByte();
                int hasFaceAlpha = first.readUnsignedByte();
                int hasFaceSkins = first.readUnsignedByte();
                int hasVertexSkins = first.readUnsignedByte();
                int modelVerticesX = first.readUnsignedShort();
                int modelVerticesY = first.readUnsignedShort();
                int modelVerticesZ = first.readUnsignedShort();
                int faceIndices = first.readUnsignedShort();
                int offset = 0;
                int vertexFlagsOffset = offset;
                offset += numVertices;
                int facesCompressTypeOffset = offset;
                offset += numFaces;
                int facePrioritiesOffset = offset;
                if (modelPriority == 255) {
                    offset += numFaces;
                }
                int faceSkinsOffset = offset;
                if (hasFaceSkins == 1) {
                    offset += numFaces;
                }
                int faceTypesOffset = offset;
                if (hasFaceTypes == 1) {
                    offset += numFaces;
                }
                int vertexSkinsOffset = offset;
                if (hasVertexSkins == 1) {
                    offset += numVertices;
                }
                int faceAlphasOffset = offset;
                if (hasFaceAlpha == 1) {
                    offset += numFaces;
                }
                int faceIndicesOffset = offset;
                offset += faceIndices;
                int faceColorsOffset = offset;
                offset += numFaces * 2;
                int faceMappingsOffset = offset;
                offset += numTextures * 6;
                int vertexXOffsetOffset = offset;
                offset += modelVerticesX;
                int vertexYOffsetOffset = offset;
                offset += modelVerticesY;
                int vertexZOffsetOffset = offset;
                offset += modelVerticesZ;
                verticesX = new int[numVertices];
                verticesY = new int[numVertices];
                verticesZ = new int[numVertices];
                faceIndicesA = new short[numFaces];
                faceIndicesB = new short[numFaces];
                faceIndicesC = new short[numFaces];
                if (numTextures > 0) {
                    faceMappings = new byte[numTextures];
                    textureMappingP = new short[numTextures];
                    textureMappingM = new short[numTextures];
                    textureMappingN = new short[numTextures];
                }
                if (hasVertexSkins == 1) {
                    vertexSkins = new int[numVertices];
                }
                if (hasFaceTypes == 1) {
                    faceTypes = new byte[numFaces];
                    faceTextures = new byte[numFaces];
                    faceMaterials = new short[numFaces];
                }
                if (modelPriority == 255) {
                    facePriorities = new byte[numFaces];
                } else {
                    priority = (byte) modelPriority;
                }
                if (hasFaceAlpha == 1) {
                    faceAlphas = new byte[numFaces];
                }
                if (hasFaceSkins == 1) {
                    faceSkins = new int[numFaces];
                }
                faceColors = new short[numFaces];
                first.setOffset(vertexFlagsOffset);
                second.setOffset(vertexXOffsetOffset);
                third.setOffset(vertexYOffsetOffset);
                fourth.setOffset(vertexZOffsetOffset);
                fifth.setOffset(vertexSkinsOffset);
                int baseX = 0;
                int baseY = 0;
                int baseZ = 0;
                for (int vertex = 0; vertex < numVertices; vertex++) {
                    int pflag = first.readUnsignedByte();
                    int xOffset = 0;
                    if ((pflag & 0x1) != 0) {
                        xOffset = second.readUnsignedSmart();
                    }
                    int yOffset = 0;
                    if ((pflag & 0x2) != 0) {
                        yOffset = third.readUnsignedSmart();
                    }
                    int zOffset = 0;
                    if ((pflag & 0x4) != 0) {
                        zOffset = fourth.readUnsignedSmart();
                    }
                    verticesX[vertex] = baseX + xOffset;
                    verticesY[vertex] = baseY + yOffset;
                    verticesZ[vertex] = baseZ + zOffset;
                    baseX = verticesX[vertex];
                    baseY = verticesY[vertex];
                    baseZ = verticesZ[vertex];
                    if (hasVertexSkins == 1) {
                        vertexSkins[vertex] = fifth.readUnsignedByte();
                    }
                }
                first.setOffset(faceColorsOffset);
                second.setOffset(faceTypesOffset);
                third.setOffset(facePrioritiesOffset);
                fourth.setOffset(faceAlphasOffset);
                fifth.setOffset(faceSkinsOffset);
                for (int face = 0; face < numFaces; face++) {
                    faceColors[face] = (short) first.readUnsignedShort();
                    if (hasFaceTypes == 1) {
                        int flag = second.readUnsignedByte();
                        if ((flag & 0x1) == 1) {
                            faceTypes[face] = (byte) 1;
                            usesFaceTypes = true;
                        } else {
                            faceTypes[face] = (byte) 0;
                        }
                        if ((flag & 0x2) == 2) {
                            faceTextures[face] = (byte) (flag >> 2);
                            faceMaterials[face] = faceColors[face];
                            faceColors[face] = (short) 127;
                            if (faceMaterials[face] != -1) {
                                usesMaterials = true;
                            }
                        } else {
                            faceTextures[face] = (byte) -1;
                            faceMaterials[face] = (short) -1;
                        }
                    }
                    if (modelPriority == 255) {
                        facePriorities[face] = (byte) third.readByte();
                    }
                    if (hasFaceAlpha == 1) {
                        faceAlphas[face] = (byte) fourth.readByte();
                    }
                    if (hasFaceSkins == 1) {
                        faceSkins[face] = fifth.readUnsignedByte();
                    }
                }
                maxIndex = -1;
                first.setOffset(faceIndicesOffset);
                second.setOffset(facesCompressTypeOffset);
                short a = 0;
                short b = 0;
                short c = 0;
                int acc = 0;
                for (int face = 0; face < numFaces; face++) {
                    int type = second.readUnsignedByte();
                    if (type == 1) {
                        a = (short) (first.readUnsignedSmart() + acc);
                        acc = a;
                        b = (short) (first.readUnsignedSmart() + acc);
                        acc = b;
                        c = (short) (first.readUnsignedSmart() + acc);
                        acc = c;
                        faceIndicesA[face] = a;
                        faceIndicesB[face] = b;
                        faceIndicesC[face] = c;
                        if (a > maxIndex) {
                            maxIndex = a;
                        }
                        if (b > maxIndex) {
                            maxIndex = b;
                        }
                        if (c > maxIndex) {
                            maxIndex = c;
                        }
                    }
                    if (type == 2) {
                        b = c;
                        c = (short) (first.readUnsignedSmart() + acc);
                        acc = c;
                        faceIndicesA[face] = a;
                        faceIndicesB[face] = b;
                        faceIndicesC[face] = c;
                        if (c > maxIndex) {
                            maxIndex = c;
                        }
                    }
                    if (type == 3) {
                        a = c;
                        c = (short) (first.readUnsignedSmart() + acc);
                        acc = c;
                        faceIndicesA[face] = a;
                        faceIndicesB[face] = b;
                        faceIndicesC[face] = c;
                        if (c > maxIndex) {
                            maxIndex = c;
                        }
                    }
                    if (type == 4) {
                        short i_149_ = a;
                        a = b;
                        b = i_149_;
                        c = (short) (first.readUnsignedSmart() + acc);
                        acc = c;
                        faceIndicesA[face] = a;
                        faceIndicesB[face] = b;
                        faceIndicesC[face] = c;
                        if (c > maxIndex) {
                            maxIndex = c;
                        }
                    }
                }
                maxIndex++;
                first.setOffset(faceMappingsOffset);
                for (int i_150_ = 0; i_150_ < numTextures; i_150_++) {
                    faceMappings[i_150_] = (byte) 0;
                    textureMappingP[i_150_] = (short) first.readUnsignedShort();
                    textureMappingM[i_150_] = (short) first.readUnsignedShort();
                    textureMappingN[i_150_] = (short) first.readUnsignedShort();
                }
                if (faceTextures != null) {
                    boolean usesMapping = false;
                    for (int face = 0; face < numFaces; face++) {
                        int texture = faceTextures[face] & 0xff;
                        if (texture != 255) {
                            if ((textureMappingP[texture] & 0xffff) == faceIndicesA[face] && (textureMappingM[texture] & 0xffff) == faceIndicesB[face] && (textureMappingN[texture] & 0xffff) == faceIndicesC[face]) {
                                faceTextures[face] = (byte) -1;
                            } else {
                                usesMapping = true;
                            }
                        }
                    }
                    if (!usesMapping) {
                        faceTextures = null;
                    }
                }
                if (!usesMaterials) {
                    faceMaterials = null;
                }
                if (!usesFaceTypes) {
                    faceTypes = null;
                }
            }
        }
    
    
        /*
         * (non-Javadoc)
         * 
         * @see com.wycody.engine.media.mesh.Mesh#encode()
         */
        @Override
        public byte[] encode() {
            /* create the master buffer */
            DynamicBuffer master = new DynamicBuffer(16 * 1024);
            /* create the temporary buffers */
            Buffer face_mappings_buffer = new DynamicBuffer(0);
            Buffer vertex_flags_buffer = new DynamicBuffer(0);
            Buffer face_types_buffer = new DynamicBuffer(0);
            Buffer face_index_types_buffer = new DynamicBuffer(0);
            Buffer face_priorities_buffer = new DynamicBuffer(0);
            Buffer face_skins_buffer = new DynamicBuffer(0);
            Buffer vertex_skins_buffer = new DynamicBuffer(0);
            Buffer face_alphas_buffer = new DynamicBuffer(0);
            Buffer face_indices_buffer = new DynamicBuffer(0);
            Buffer face_materials_buffer = new DynamicBuffer(0);
            Buffer face_textures_buffer = new DynamicBuffer(0);
            Buffer face_colors_buffer = new DynamicBuffer(0);
            Buffer vertex_x_buffer = new DynamicBuffer(0);
            Buffer vertex_y_buffer = new DynamicBuffer(0);
            Buffer vertex_z_buffer = new DynamicBuffer(0);
            Buffer simple_textures_buffer = new DynamicBuffer(0);
            Buffer complex_textures_buffer = new DynamicBuffer(0);
            Buffer texture_scale_buffer = new DynamicBuffer(0);
            Buffer texture_rotation_buffer = new DynamicBuffer(0);
            Buffer texture_direction_buffer = new DynamicBuffer(0);
            Buffer texture_translation_buffer = new DynamicBuffer(0);
            Buffer particle_effects_buffer = new DynamicBuffer(0);
            Buffer footer_buffer = new DynamicBuffer(0);
            Buffer[] buffers = new Buffer[] { face_mappings_buffer, vertex_flags_buffer, face_types_buffer, face_index_types_buffer, face_priorities_buffer, face_skins_buffer, vertex_skins_buffer, face_alphas_buffer, face_indices_buffer, face_materials_buffer, face_textures_buffer, face_colors_buffer, vertex_x_buffer, vertex_y_buffer, vertex_z_buffer, simple_textures_buffer, complex_textures_buffer, texture_scale_buffer, texture_rotation_buffer,
                    texture_direction_buffer, texture_translation_buffer, particle_effects_buffer, footer_buffer };
            /* serialize the face mapping types */
            if (numTextures > 0) {
                for (int face = 0; face < numTextures; face++) {
                    face_mappings_buffer.writeByte(faceMappings[face]);
                }
            }
    
    
            /* create the vertices variables */
            boolean hasVertexSkins = vertexSkins != null;
            boolean hasExtendedVertexSkins = false;
            /* serialize the vertices */
            int baseX = 0, baseY = 0, baseZ = 0;
            for (int vertex = 0; vertex < numVertices; vertex++) {
                int x = verticesX[vertex];
                int y = verticesY[vertex];
                int z = verticesZ[vertex];
                int xoff = x - baseX;
                int yoff = y - baseY;
                int zoff = z - baseZ;
                int flag = 0;
                if (xoff != 0) {
                    vertex_x_buffer.writeUnsignedSmart(xoff);
                    flag |= 0x1;
                }
                if (yoff != 0) {
                    vertex_y_buffer.writeUnsignedSmart(yoff);
                    flag |= 0x2;
                }
                if (zoff != 0) {
                    vertex_z_buffer.writeUnsignedSmart(zoff);
                    flag |= 0x4;
                }
                vertex_flags_buffer.writeByte(flag);
                verticesX[vertex] = baseX + xoff;
                verticesY[vertex] = baseY + yoff;
                verticesZ[vertex] = baseZ + zoff;
                baseX = verticesX[vertex];
                baseY = verticesY[vertex];
                baseZ = verticesZ[vertex];
                if (hasVertexSkins) {
                    int weight = vertexSkins[vertex];
                    if (weight >= -1 && weight <= 254) {
                        vertex_skins_buffer.writeByte(weight);
                    } else {
                        vertex_skins_buffer.writeSmart(weight + 1);
                        hasExtendedVertexSkins = true;
                    }
                }
            }
            /* create the faces variables */
            boolean hasFaceTypes = faceTypes != null;
            boolean hasFacePriorities = facePriorities != null;
            boolean hasFaceAlpha = faceAlphas != null;
            boolean hasFaceSkins = faceSkins != null;
            boolean hasExtendedFaceSkins = false;
            boolean hasFaceTextures = faceMaterials != null;
            /* serialize the faces */
            for (int face = 0; face < numFaces; face++) {
                face_colors_buffer.writeShort(faceColors[face]);
                if (hasFaceTypes) {
                    face_types_buffer.writeByte(faceTypes[face]);
                }
                if (hasFacePriorities) {
                    face_priorities_buffer.writeByte(facePriorities[face]);
                }
                if (hasFaceAlpha) {
                    face_alphas_buffer.writeByte(faceAlphas[face]);
                }
                if (hasFaceSkins) {
                    int weight = faceSkins[face];
                    if (weight >= -1 && weight <= 254) {
                        face_skins_buffer.writeByte(weight);
                    } else {
                        face_skins_buffer.writeSmart(weight + 1);
                        hasExtendedFaceSkins = true;
                    }
                }
                if (hasFaceTextures) {
                    face_materials_buffer.writeShort(faceMaterials[face] + 1);
                }
                if (faceTextures != null) {
                    if (faceMaterials[face] != -1) {
                        face_textures_buffer.writeByte(faceTextures[face] + 1);
                    }
                }
            }
            /* serialize the face indices */
            emcodeIndices(face_indices_buffer, face_index_types_buffer);
            /* serialize the texture mapping */
            encodeMapping(simple_textures_buffer, complex_textures_buffer, texture_scale_buffer, texture_rotation_buffer, texture_direction_buffer, texture_translation_buffer);
            /* create the particle effects variables */
            boolean hasParticleEffects = emitters != null || effectors != null;
            /* serialize the particle effects */
            if (hasParticleEffects) {
                int numEmitters = emitters != null ? emitters.length : 0;
                if (numEmitters > 0) {
                    for (int index = 0; index < numEmitters; index++) {
                        EmissiveTriangle triangle = emitters[index];
                        particle_effects_buffer.writeShort(triangle.getEmitter());
                        particle_effects_buffer.writeShort(triangle.getFace());
                    }
                }
                int numEffectors = effectors != null ? effectors.length : 0;
                if (numEffectors > 0) {
                    for (int index = 0; index < numEffectors; index++) {
                        EffectiveVertex vertex = effectors[index];
                        particle_effects_buffer.writeShort(vertex.getEffector());
                        particle_effects_buffer.writeShort(vertex.getVertex());
                    }
                }
            }
            /* create the billboards variables */
            boolean hasBillboards = billboards != null;
            boolean hasExtendedBillboards = false;
            /* serialize the billboards */
            if (hasBillboards) {
                particle_effects_buffer.writeByte(billboards.length);
                for (int index = 0; index < billboards.length; index++) {
                    FaceBillboard billboard = billboards[index];
                    particle_effects_buffer.writeShort(billboard.getId());
                    particle_effects_buffer.writeShort(billboard.getFace());
                    int depth = billboard.getDepth();
                    if (depth >= -1 && depth <= 254) { // 0 - 255
                        particle_effects_buffer.writeByte(depth);
                    } else {
                        particle_effects_buffer.writeSmart(depth + 1);
                        hasExtendedBillboards = true;
                    }
                    particle_effects_buffer.writeByte(billboard.getDistance());
                }
            }
            /* create the footer data */
            boolean hasVersion = version != DEFAULT_VERSION;
            if (hasVersion) {
                footer_buffer.writeByte(version);
            }
            footer_buffer.writeShort(numVertices);
            footer_buffer.writeShort(numFaces);
            footer_buffer.writeByte(numTextures);
            int flags = 0;
            if (hasFaceTypes) {
                flags |= 0x1;
            }
            if (hasParticleEffects) {
                flags |= 0x2;
            }
            if (hasBillboards) {
                flags |= 0x4;
            }
            if (hasVersion) {
                flags |= 0x8;
            }
            if (hasExtendedVertexSkins) {
                flags |= 0x10;
            }
            if (hasExtendedFaceSkins) {
                flags |= 0x20;
            }
            if (hasExtendedBillboards) {
                flags |= 0x40;
            }
            footer_buffer.writeByte(flags);
            footer_buffer.writeByte(hasFacePriorities ? -1 : priority);
            footer_buffer.writeBoolean(hasFaceAlpha);
            footer_buffer.writeBoolean(hasFaceSkins);
            footer_buffer.writeBoolean(hasFaceTextures);
            footer_buffer.writeBoolean(hasVertexSkins);
            footer_buffer.writeShort(vertex_x_buffer.size());
            footer_buffer.writeShort(vertex_y_buffer.size());
            footer_buffer.writeShort(vertex_z_buffer.size());
            footer_buffer.writeShort(face_indices_buffer.size());
            footer_buffer.writeShort(face_textures_buffer.size());
            if (hasExtendedVertexSkins) {
                footer_buffer.writeShort(vertex_skins_buffer.size());
            }
            if (hasExtendedFaceSkins) {
                footer_buffer.writeShort(face_skins_buffer.size());
            }
            for (int i = 0; i < buffers.length; i++) {
                Buffer buffer = buffers[i];
                master.write(buffer.getDataTrimmed());
            }
            master.writeByte(255);
            master.writeByte(255);
            return master.getDataTrimmed();
        }
    
    
        /**
         * Decodes the face indices from the given buffers.
         * 
         * @param indicesBuffer
         *            the face index buffer.
         * @param typesBuffer
         *            the face type buffer.
         */
        private void decodeIndices(Buffer indicesBuffer, Buffer typesBuffer) {
            short a = 0;
            short b = 0;
            short c = 0;
            int acc = 0;
            for (int face = 0; face < numFaces; face++) {
                int type = typesBuffer.readUnsignedByte();
                if (type == 1) {
                    a = (short) (indicesBuffer.readUnsignedSmart() + acc);
                    acc = a;
                    b = (short) (indicesBuffer.readUnsignedSmart() + acc);
                    acc = b;
                    c = (short) (indicesBuffer.readUnsignedSmart() + acc);
                    acc = c;
                    faceIndicesA[face] = a;
                    faceIndicesB[face] = b;
                    faceIndicesC[face] = c;
                    if (a > maxIndex) {
                        maxIndex = a;
                    }
                    if (b > maxIndex) {
                        maxIndex = b;
                    }
                    if (c > maxIndex) {
                        maxIndex = c;
                    }
                }
                if (type == 2) {
                    b = c;
                    c = (short) (indicesBuffer.readUnsignedSmart() + acc);
                    acc = c;
                    faceIndicesA[face] = a;
                    faceIndicesB[face] = b;
                    faceIndicesC[face] = c;
                    if (c > maxIndex) {
                        maxIndex = c;
                    }
                }
                if (type == 3) {
                    a = c;
                    c = (short) (indicesBuffer.readUnsignedSmart() + acc);
                    acc = c;
                    faceIndicesA[face] = a;
                    faceIndicesB[face] = b;
                    faceIndicesC[face] = c;
                    if (c > maxIndex) {
                        maxIndex = c;
                    }
                }
                if (type == 4) {
                    short bk = a;
                    a = b;
                    b = bk;
                    c = (short) (indicesBuffer.readUnsignedSmart() + acc);
                    acc = c;
                    faceIndicesA[face] = a;
                    faceIndicesB[face] = b;
                    faceIndicesC[face] = c;
                    if (c > maxIndex) {
                        maxIndex = c;
                    }
                }
            }
            maxIndex++;
        }
    
    
        /**
         * Decodes the texture mapping from the given buffers.
         * 
         * @param simpleBuffer
         *            the simple texture mappings buffer.
         * @param complexBuffer
         *            the complex texture mappings buffer.
         * @param scaleBuffer
         *            the textures scale buffer.
         * @param rotationBuffer
         *            the textures rotation buffer.
         * @param directionBuffer
         *            the textures direction buffer.
         * @param translationBuffer
         *            the textures translation buffer.
         */
        private void decodeMapping(Buffer simpleBuffer, Buffer complexBuffer, Buffer scaleBuffer, Buffer rotationBuffer, Buffer directionBuffer, Buffer translationBuffer) {
            for (int index = 0; index < numTextures; index++) {
                int type = faceMappings[index] & 0xff;
                if (type == 0) {
                    textureMappingP[index] = (short) simpleBuffer.readUnsignedShort();
                    textureMappingM[index] = (short) simpleBuffer.readUnsignedShort();
                    textureMappingN[index] = (short) simpleBuffer.readUnsignedShort();
                }
                if (type == 1) {
                    textureMappingP[index] = (short) complexBuffer.readUnsignedShort();
                    textureMappingM[index] = (short) complexBuffer.readUnsignedShort();
                    textureMappingN[index] = (short) complexBuffer.readUnsignedShort();
                    if (version < 15) {
                        textureScaleX[index] = scaleBuffer.readUnsignedShort();
                        if (version < 14) {
                            textureScaleY[index] = scaleBuffer.readUnsignedShort();
                        } else {
                            textureScaleY[index] = scaleBuffer.readUnsignedTriByte();
                        }
                        textureScaleZ[index] = scaleBuffer.readUnsignedShort();
                    } else {
                        textureScaleX[index] = scaleBuffer.readUnsignedTriByte();
                        textureScaleY[index] = scaleBuffer.readUnsignedTriByte();
                        textureScaleZ[index] = scaleBuffer.readUnsignedTriByte();
                    }
                    textureRotation[index] = (byte) rotationBuffer.readByte();
                    textureDirection[index] = (byte) directionBuffer.readByte();
                    textureSpeed[index] = translationBuffer.readByte();
                }
                if (type == 2) {
                    textureMappingP[index] = (short) complexBuffer.readUnsignedShort();
                    textureMappingM[index] = (short) complexBuffer.readUnsignedShort();
                    textureMappingN[index] = (short) complexBuffer.readUnsignedShort();
                    if (version < 15) {
                        textureScaleX[index] = scaleBuffer.readUnsignedShort();
                        if (version < 14) {
                            textureScaleY[index] = scaleBuffer.readUnsignedShort();
                        } else {
                            textureScaleY[index] = scaleBuffer.readUnsignedTriByte();
                        }
                        textureScaleZ[index] = scaleBuffer.readUnsignedShort();
                    } else {
                        textureScaleX[index] = scaleBuffer.readUnsignedTriByte();
                        textureScaleY[index] = scaleBuffer.readUnsignedTriByte();
                        textureScaleZ[index] = scaleBuffer.readUnsignedTriByte();
                    }
                    textureRotation[index] = (byte) rotationBuffer.readByte();
                    textureDirection[index] = (byte) directionBuffer.readByte();
                    textureSpeed[index] = translationBuffer.readByte();
                    textureTransU[index] = translationBuffer.readByte();
                    textureTransV[index] = translationBuffer.readByte();
                }
                if (type == 3) {
                    textureMappingP[index] = (short) complexBuffer.readUnsignedShort();
                    textureMappingM[index] = (short) complexBuffer.readUnsignedShort();
                    textureMappingN[index] = (short) complexBuffer.readUnsignedShort();
                    if (version < 15) {
                        textureScaleX[index] = scaleBuffer.readUnsignedShort();
                        if (version < 14) {
                            textureScaleY[index] = scaleBuffer.readUnsignedShort();
                        } else {
                            textureScaleY[index] = scaleBuffer.readUnsignedTriByte();
                        }
                        textureScaleZ[index] = scaleBuffer.readUnsignedShort();
                    } else {
                        textureScaleX[index] = scaleBuffer.readUnsignedTriByte();
                        textureScaleY[index] = scaleBuffer.readUnsignedTriByte();
                        textureScaleZ[index] = scaleBuffer.readUnsignedTriByte();
                    }
                    textureRotation[index] = (byte) rotationBuffer.readByte();
                    textureDirection[index] = (byte) directionBuffer.readByte();
                    textureSpeed[index] = translationBuffer.readByte();
                }
            }
        }
    
    
        /**
         * Encodes the texture mappings.
         * 
         * @param simple
         *            the simple mapping buffer.
         * @param complex
         *            the complex mapping buffer.
         * @param scale
         *            the scale buffer.
         * @param rotation
         *            the rotation buffer.
         * @param direction
         *            the direction buffer.
         * @param translation
         *            the translation buffer.
         */
        private void encodeMapping(Buffer simple, Buffer complex, Buffer scale, Buffer rotation, Buffer direction, Buffer translation) {
            for (int face = 0; face < numTextures; face++) {
                int type = faceMappings[face] & 0xff;
                if (type == 0) {
                    simple.writeShort(textureMappingP[face]);
                    simple.writeShort(textureMappingM[face]);
                    simple.writeShort(textureMappingN[face]);
                } else {
                    int scaleX = textureScaleX[face];
                    int scaleY = textureScaleY[face];
                    int scaleZ = textureScaleZ[face];
                    if (type == 1) {
                        complex.writeShort(textureMappingP[face]);
                        complex.writeShort(textureMappingM[face]);
                        complex.writeShort(textureMappingN[face]);
                        if (version >= 15 || scaleX > 0xffff || scaleZ > 0xffff) {
                            if (version < 15) {
                                version = 15;
                            }
                            scale.writeTriByte(scaleX);
                            scale.writeTriByte(scaleY);
                            scale.writeTriByte(scaleZ);
                        } else {
                            scale.writeShort(scaleX);
                            if (version < 14 && scaleY > 0xffff) {
                                version = 14;
                            }
                            if (version < 14) {
                                scale.writeShort(scaleY);
                            } else {
                                scale.writeTriByte(scaleY);
                            }
                            scale.writeShort(scaleZ);
                        }
                        rotation.writeByte(textureRotation[face]);
                        direction.writeByte(textureDirection[face]);
                        translation.writeByte(textureSpeed[face]);
                    } else if (type == 2) {
                        complex.writeShort(textureMappingP[face]);
                        complex.writeShort(textureMappingM[face]);
                        complex.writeShort(textureMappingN[face]);
                        if (version >= 15 || scaleX > 0xffff || scaleZ > 0xffff) {
                            if (version < 15) {
                                version = 15;
                            }
                            scale.writeTriByte(scaleX);
                            scale.writeTriByte(scaleY);
                            scale.writeTriByte(scaleZ);
                        } else {
                            scale.writeShort(scaleX);
                            if (version < 14 && scaleY > 0xffff) {
                                version = 14;
                            }
                            if (version < 14) {
                                scale.writeShort(scaleY);
                            } else {
                                scale.writeTriByte(scaleY);
                            }
                            scale.writeShort(scaleZ);
                        }
                        rotation.writeByte(textureRotation[face]);
                        direction.writeByte(textureDirection[face]);
                        translation.writeByte(textureSpeed[face]);
                        translation.writeByte(textureTransU[face]);
                        translation.writeByte(textureTransV[face]);
                    } else if (type == 3) {
                        complex.writeShort(textureMappingP[face]);
                        complex.writeShort(textureMappingM[face]);
                        complex.writeShort(textureMappingN[face]);
    
    
                        if (version >= 15 || scaleX > 0xffff || scaleZ > 0xffff) {
                            if (version < 15) {
                                version = 15;
                            }
                            scale.writeTriByte(scaleX);
                            scale.writeTriByte(scaleY);
                            scale.writeTriByte(scaleZ);
                        } else {
                            scale.writeShort(scaleX);
                            if (version < 14 && scaleY > 0xffff) {
                                version = 14;
                            }
                            if (version < 14) {
                                scale.writeShort(scaleY);
                            } else {
                                scale.writeTriByte(scaleY);
                            }
                            scale.writeShort(scaleZ);
                        }
                        rotation.writeByte(textureRotation[face]);
                        direction.writeByte(textureDirection[face]);
                        translation.writeByte(textureSpeed[face]);
                    }
                }
            }
        }
    
    
        /**
         * Encodes the indices list.
         * 
         * @param ibuffer
         *            the indices buffer.
         * @param tbuffer
         *            the indices compression type buffer.
         */
        private void emcodeIndices(Buffer ibuffer, Buffer tbuffer) {
            short lasta = 0;
            short lastb = 0;
            short lastc = 0;
            int pacc = 0;
            for (int fndex = 0; fndex < numFaces; fndex++) {
                short cura = faceIndicesA[fndex];
                short curb = faceIndicesB[fndex];
                short curc = faceIndicesC[fndex];
                if (cura == lastb && curb == lasta && curc != lastc) {
                    tbuffer.writeByte(4);
                    ibuffer.writeUnsignedSmart(curc - pacc);
                    short back = lasta;
                    lasta = lastb;
                    lastb = back;
                    pacc = lastc = curc;
                } else if (cura == lastc && curb == lastb && curc != lastc) {
                    tbuffer.writeByte(3);
                    ibuffer.writeUnsignedSmart(curc - pacc);
                    lasta = lastc;
                    pacc = lastc = curc;
                } else if (cura == lasta && curb == lastc && curc != lastc) {
                    tbuffer.writeByte(2);
                    ibuffer.writeUnsignedSmart(curc - pacc);
                    lastb = lastc;
                    pacc = lastc = curc;
                } else {
                    tbuffer.writeByte(1);
                    ibuffer.writeUnsignedSmart(cura - pacc);
                    ibuffer.writeUnsignedSmart(curb - cura);
                    ibuffer.writeUnsignedSmart(curc - curb);
                    lasta = cura;
                    lastb = curb;
                    pacc = lastc = curc;
                }
    
    
            }
        }
    
    
    }
    FaceBillboard
    Code:
    package com.wycody.engine.media.mesh;
    
    
    /**
     * Created at: Apr 15, 2017 11:09:48 PM
     * 
     * @author Walied-Yassen
     */
    public class FaceBillboard {
    
    
        /**
         * The billboard ID.
         */
        private int id;
    
    
        /**
         * The billboard face.
         */
        private int face;
    
    
        /**
         * The billboard depth.
         */
        private int skin;
    
    
        /**
         * The billboard distance.
         */
        private int distance;
    
    
        /**
         * Constructs a new {@link FaceBillboard} object instance.
         * 
         * @param id
         *            the billboard ID.
         * @param face
         *            the billboard face.
         * @param skin
         *            the billboard skin.
         * @param distance
         *            the billboard distance.
         */
        public FaceBillboard(int id, int face, int skin, int distance) {
            this.id = id;
            this.face = face;
            this.skin = skin;
            this.distance = distance;
        }
    
    
        /**
         * Gets the billboard id.
         * 
         * @return the billboard id.
         */
        public int getId() {
            return id;
        }
    
    
        /**
         * Sets the billboard id.
         * 
         * @param distance
         *            the new id to set.
         */
        public void setId(int id) {
            this.id = id;
        }
    
    
        /**
         * Gets the billboard face.
         * 
         * @return the billboard face.
         */
        public int getFace() {
            return face;
        }
    
    
        /**
         * Sets the billboard face.
         * 
         * @param distance
         *            the new face to set.
         */
        public void setFace(int face) {
            this.face = face;
        }
    
    
        /**
         * Gets the billboard depth.
         * 
         * @return the billboard depth.
         */
        public int getDepth() {
            return skin;
        }
    
    
        /**
         * Sets the billboard depth.
         * 
         * @param distance
         *            the new depth to set.
         */
        public void setDepth(int depth) {
            this.skin = depth;
        }
    
    
        /**
         * Gets the billboard distance.
         * 
         * @return the billboard distance.
         */
        public int getDistance() {
            return distance;
        }
    
    
        /**
         * Sets the billboard distance.
         * 
         * @param distance
         *            the new distance to set.
         */
        public void setDistance(int distance) {
            this.distance = distance;
        }
    
    
    }

    Methods
    Code:
    
        /**
         * Reads a smart value from the buffer.
         * 
         * @return the read smart value.
         * 
         */
        public int readSmart() {
            int value = data[offset] & 0xff;
            if (value < 128) {
                return readUnsignedByte();
            }
            return readUnsignedShort() - 32768;
        }
    
    
        /**
         * Reads a smart value from the buffer (supports -1).
         * 
         * @return the read smart value.
         */
        public int readSmartNS() {
            return readSmart() - 1;
        }
    
    
        /**
         * Writes a smart value to the buffer.
         * 
         * @param value
         *            the value to write.
         */
        public void writeSmart(int value) {
            if (value >= 128) {
                writeShort(value + 32768);
            } else {
                writeByte(value);
            }
        }
    
    
        /**
         * Reads an unsigned smart value from the buffer.
         * 
         * @return the read unsigned smart value.
         * 
         */
        public int readUnsignedSmart() {
            int value = data[offset] & 0xff;
            if (value < 128) {
                return readUnsignedByte() - 64;
            }
            return readUnsignedShort() - 49152;
        }
    
    
        /**
         * Writes an unsigned smart value to the buffer.
         * 
         * @param value
         *            the value to write.
         */
        public void writeUnsignedSmart(int value) {
            if (value < 64 && value >= -64) {
                writeByte(value + 64);
                return;
            }
            if (value < 16384 && value >= -16384) {
                writeShort(value + 49152);
                return;
            } else {
                System.out.println("Error psmart out of range: " + value);
                return;
            }
        }
    
    
        /**
         * Reads a smart words from the buffer.
         * 
         * @return the read smart value.
         */
        public int readSmartWords() {
            int value = 0;
            int incr;
            for (incr = readSmart(); incr == 32767; incr = readSmart()) {
                value += 32767;
            }
            value += incr;
            return value;
        }
    
    
        /**
         * Writes a smart words to the buffer.
         * 
         * @param value
         *            the smart value to write.
         */
        public void writeSmartWords(int value) {
            while (value > 32767) {
                writeSmart(value);
                value -= 32767;
            }
            if (value > 0) {
                writeSmart(value);
            }
        }
    
    
        /**
         * Reads a big smart value from the buffer.
         * 
         * @return the read smart value.
         */
        public int readBigSmart() {
            if (data[offset] < 0) {
                return readInt() & 0x7fffffff;
            }
            return readUnsignedShort();
        }
    
    
        /**
         * Reads a big smart value from the buffer (termination value
         * <code>-1</code> supported).
         * 
         * @return the read smart value.
         */
        public int readBigSmartNS() {
            if (data[offset] < 0) {
                return readInt() & 0x7fffffff;
            }
            int value = readUnsignedShort();
            if (value == 32767) {
                return -1;
            }
            return value;
        }
    
    
        /**
         * Writes a big smart value to the buffer.
         * 
         * @param value
         *            the value to write.
         */
        public void writeBigSmart(int value) {
            if (value > 32767) {
                writeInt(value - Integer.MAX_VALUE - 1);
            } else {
                writeShort(value >= 0 ? value : 32767);
            }
        }
    NO ONE IS PERFECT
    "No one in this world is pure and perfect, if you avoid people for their little mistakes you will be always alone in this world, so judge less and love more."
    "Ship in the harbor is safe, but that is not what ships are built for."
    Reply With Quote  
     


  2. #2  
    Donator


    Join Date
    Jul 2013
    Posts
    1,233
    Thanks given
    1
    Thanks received
    493
    Rep Power
    0
    all these offsets and bitwise operators making this look chinese to me. Thanks for the release walied. ur the og
    Reply With Quote  
     

  3. #3  
    Computer Engineer
    Join Date
    Aug 2014
    Posts
    1,051
    Thanks given
    365
    Thanks received
    215
    Rep Power
    16
    Amazing contribution , great job as always Wally.
    Reply With Quote  
     

  4. #4  
    Developer


    Join Date
    Aug 2012
    Posts
    2,493
    Thanks given
    180
    Thanks received
    1,732
    Rep Power
    2487
    i remember how long it took me to write a model encoder in 2015, one small mistake and ur gone searching through everything for such a long time

    but yea gj
    Reply With Quote  
     

  5. #5  
    Registered Member
    Join Date
    Jun 2017
    Posts
    47
    Thanks given
    1
    Thanks received
    4
    Rep Power
    10
    Hey sorry for the stupid question but what is model encoder?
    Reply With Quote  
     


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. RuneScape Model Grabber/Viewer
    By Mrquarter in forum Tools
    Replies: 32
    Last Post: 08-10-2008, 10:52 PM
  2. New Cache Models 2007 June :O
    By Bobster in forum Downloads
    Replies: 8
    Last Post: 07-30-2008, 09:47 AM
  3. RuneScape Models
    By madman00901 in forum Configuration
    Replies: 22
    Last Post: 03-10-2008, 06:06 PM
  4. (not a sig) 3d models (maybe for a server)
    By kingbaumann in forum Showcase
    Replies: 41
    Last Post: 08-16-2007, 09:12 PM
  5. Model List
    By Zachera in forum RS2 Client
    Replies: 1
    Last Post: 05-01-2007, 02:40 PM
Posting Permissions
  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •