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);
}
}