Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
746 lines (631 sloc) 23.6 KB
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package ModelFormat.QuakeMDL;
import Geometry.Vec3;
import Images.PCX;
import ModelFormat.WavefrontOBJ.OBJ;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import Utility.BinaryFileReader;
import ModelFormat.ModelFormat;
import javax.swing.JOptionPane;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
/**
*
* @author cjones
*/
public class MDL extends ModelFormat
{
public static final int MDL_HEADER_SIZE = 84; //size in bytes of the header
public static int[][] colourMap;
private MDLHeader header;
private MDLSkin[] skins;
private MDLTexCoord[] texCoords;
private MDLTriangle[] triangles;
private MDLFrame[] frames;
//<editor-fold defaultstate="collapsed" desc="Constructor from a filename">
public MDL(String _filename)
{
BinaryFileReader data = new BinaryFileReader(_filename);
header = new MDLHeader(data.nextInt(),
data.nextInt(),
data.nextFloatVec(),
data.nextFloatVec(),
data.nextFloat(),
data.nextFloatVec(),
data.nextInt(),
data.nextInt(),
data.nextInt(),
data.nextInt(),
data.nextInt(),
data.nextInt(),
data.nextInt(),
data.nextInt(),
data.nextFloat());
//header is 84 bytes long
int group, nb;
float[] time;
skins = new MDLSkin[header.getNumSkins()]; //create an array of skins based on how many skins there are.
int[] skinData;
for (int i = 0; i < skins.length; i++) //fill the skin data in
{
skinData = new int[header.getSkinWidth() * header.getSkinHeight()];
group = data.nextInt();
if (group == 1) //grouped frame, extra bytes here for some stuff
{
nb = data.nextInt();
time = new float[nb];
}
for (int j = 0; j < (header.getSkinWidth() * header.getSkinHeight());
j++)
{
skinData[j] = data.nextUnsignedByte();
}
//skins[i] = new MDLSkin(group, nb, time, skinData);
skins[i] = new MDLSkin(group, skinData);
}
//fread (mdl->texcoords, sizeof (struct mdl_texcoord_t), mdl->header.num_verts, fp);
texCoords = new MDLTexCoord[header.getNumVerts()];
for (int i = 0; i < texCoords.length; i++)
{
texCoords[i] = new MDLTexCoord(data.nextInt(), data.nextInt(), data.nextInt());
//System.out.println("texcoords: " + texCoords[i]);
}
//fread (mdl->triangles, sizeof (struct mdl_triangle_t), mdl->header.num_tris, fp);
triangles = new MDLTriangle[header.getNumTris()];
for (int i = 0; i < triangles.length; i++)
triangles[i] = new MDLTriangle(data.nextInt(), data.nextIntVec());
MDLFrameElement frame;
int type;
MDLVertex mins, maxs, verts[];
String name;
frames = new MDLFrame[header.getNumFrames()];
for (int i = 0; i < frames.length; i++)
{
//System.out.println("Start index: " + index);
type = data.nextInt(); //fread (&mdl->frames[i].type, sizeof (long), 1, fp);
mins = new MDLVertex(data.nextUnsignedByteVec(), data.nextUnsignedByte()); //fread (&mdl->frames[i].frame.bboxmin, sizeof (struct mdl_vertex_t), 1, fp);
maxs = new MDLVertex(data.nextUnsignedByteVec(), data.nextUnsignedByte()); //fread (&mdl->frames[i].frame.bboxmax, sizeof (struct mdl_vertex_t), 1, fp);
name = data.nextString(16); //fread (mdl->frames[i].frame.name, sizeof (char), 16, fp);
//fread (mdl->frames[i].frame.verts, sizeof (struct mdl_vertex_t), mdl->header.num_verts, fp);
verts = new MDLVertex[header.getNumVerts()];
for (int j = 0; j < verts.length; j++)
verts[j] = new MDLVertex(data.nextUnsignedByteVec(), data.nextUnsignedByte());
frame = new MDLFrameElement(mins, maxs, name, verts);
frames[i] = new MDLFrame(type, frame);
//System.out.println(frames[i]);
//System.out.println("End index: " + index);
}
}
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Private class used in OBJ -> MDL conversion">
private class OBJ2MDLVert
{
public int OBJVertIndex;
public int OBJTextIndex;
public OBJ2MDLVert(int OBJVertIndex, int OBJTextIndex)
{
this.OBJVertIndex = OBJVertIndex;
this.OBJTextIndex = OBJTextIndex;
}
@Override
public boolean equals(Object obj)
{
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final OBJ2MDLVert other = (OBJ2MDLVert) obj;
if (this.OBJVertIndex != other.OBJVertIndex)
return false;
//if (this.OBJTextIndex != other.OBJTextIndex)
// return false;
return true;
}
@Override
public int hashCode()
{
int hash = 7;
hash = 37 * hash + this.OBJVertIndex;
return hash;
}
@Override
public String toString()
{
return String.format("v: %d, t: %d", OBJVertIndex, OBJTextIndex);
}
}
//</editor-fold>
public MDL(OBJ obj)
{
int[][][] objTris = obj.getTris(); //for convenience
header = new MDLHeader(); //blank header, we'll be filling this in as we process to OBJ
triangles = new MDLTriangle[objTris.length]; //make the array of triangles (OBJ -> MDL no change in # of tris)
///// Set the header to the correct number of tris.
header.setNumTris(triangles.length);
ArrayList<OBJ2MDLVert> newVertices = new ArrayList();
for (int i = 0; i < objTris.length; i++)
{
int[][] objTri = objTris[i];
int[] mdlTriVertIndices = new int[3];
for (int vIndex = 0; vIndex < 3; vIndex++)
{
boolean differentTextureIndex = false;
OBJ2MDLVert temp = new OBJ2MDLVert(objTri[vIndex][0], objTri[vIndex][1]);
if (!newVertices.contains(temp) || newVertices.isEmpty())
{ //DOESN'T contain this obj vert index yet, so this is simple, add it as a new vertex
newVertices.add(temp);
/*
This last bit is the 'magic':
We make a new triangle with 3 indices, and we assign the NEW index (size - 1)
to this triangle. This will be the MDL triangles.
*/
mdlTriVertIndices[vIndex] = newVertices.size() - 1;
}
else //DOES contain this obj vert index. Now we need to check if it is referencing the same tex coord or not.
{
for (int checkIndex = 0; checkIndex < newVertices.size(); checkIndex++)
{
/*
If the tex coord is NOT the same, than this MUST be a
new vertex, so we create a new vertex with the same
index to the vert, but the different tex coord.
This will become a NEW MDLVertex.
*/
if (newVertices.get(checkIndex).OBJVertIndex == temp.OBJVertIndex
&& newVertices.get(checkIndex).OBJTextIndex != temp.OBJTextIndex)
{
differentTextureIndex = true;
newVertices.add(temp);
/*
This last bit is the 'magic':
We make a new triangle with 3 indices, and we assign the NEW index (size - 1)
to this triangle. This will be the MDL triangles.
*/
mdlTriVertIndices[vIndex] = newVertices.size() - 1;
break;
}
}
if (!differentTextureIndex)
{
for (int searchIndex = 0; searchIndex < newVertices.size(); searchIndex++)
{
if (objTri[vIndex][0] == newVertices.get(searchIndex).OBJVertIndex //match the index from the OBJ to the newVertices index
&& newVertices.get(searchIndex).OBJTextIndex == temp.OBJTextIndex)
{
/*
This last bit is the 'magic':
Since THIS particular vertex was identical to another
one already in the list, we just search through that
list, find the index, and assign that index to the new
tri.
*/
mdlTriVertIndices[vIndex] = searchIndex;
break;
}
}
}
}
}
triangles[i] = new MDLTriangle(1, mdlTriVertIndices); //These are properly converted MDL triangles now!
}
/*
We now know how many actual vertices there are and what texCoord each of them
will have!
*/
///// Set the header to the correct number of verts.
header.setNumVerts(newVertices.size());
// Since we know how many verts there are, we know how many texcoords there are as well.
texCoords = new MDLTexCoord[header.getNumVerts()];
for (int i = 0; i < texCoords.length; i++)
{
int s = (int) ((obj.getTextureCoordinates()[newVertices.get(i).OBJTextIndex].x) * obj.getTextureWidth() + 0.0f);
int t = (int) ((obj.getTextureCoordinates()[newVertices.get(i).OBJTextIndex].y) * obj.getTextureHeight() + 0.0f);
texCoords[i] = new MDLTexCoord(0, s, t);
//System.out.println("texcoords: " + texCoords[i]);
}
int numFrames = obj.getNumFrames();
///// Update header to the correct number of frames
header.setNumFrames(numFrames);
frames = new MDLFrame[numFrames]; //create the array for the number of frames
Vec3 mins = new Vec3(obj.getFrame(0).getMins()), maxs = new Vec3(obj.getFrame(0).getMins());
for (int frameIndex = 0; frameIndex < numFrames; frameIndex++)
{
if (obj.getFrame(frameIndex).getMins().x < mins.x)
mins.x = obj.getFrame(frameIndex).getMins().x;
if (obj.getFrame(frameIndex).getMins().y < mins.y)
mins.y = obj.getFrame(frameIndex).getMins().y;
if (obj.getFrame(frameIndex).getMins().z < mins.z)
mins.z = obj.getFrame(frameIndex).getMins().z;
if (obj.getFrame(frameIndex).getMaxs().x > maxs.x)
maxs.x = obj.getFrame(frameIndex).getMaxs().x;
if (obj.getFrame(frameIndex).getMaxs().y > maxs.y)
maxs.y = obj.getFrame(frameIndex).getMaxs().y;
if (obj.getFrame(frameIndex).getMaxs().z > maxs.z)
maxs.z = obj.getFrame(frameIndex).getMaxs().z;
}
Vec3 scale = new Vec3();
scale = (maxs.subtract(mins)).scale(1 / 255f);
/*scale.x = (maxs.x - mins.x) / 255.0f;
scale.y = (maxs.y - mins.y) / 255.0f;
scale.z = (maxs.z - mins.z) / 255.0f;*/
header.setScale(scale);
header.setTranslate(mins);
for (int frameIndex = 0; frameIndex < numFrames; frameIndex++)
{
MDLVertex[] frameVerts = new MDLVertex[header.getNumVerts()];
for (int vIndex = 0; vIndex < header.getNumVerts(); vIndex++)
{
Vec3 vertOrigin = obj.getFrame(frameIndex).getVertices()[newVertices.get(vIndex).OBJVertIndex];
vertOrigin = vertOrigin.subtract(header.getTranslate());
vertOrigin.x = vertOrigin.x / header.getScale().x;
vertOrigin.y = vertOrigin.y / header.getScale().y;
vertOrigin.z = vertOrigin.z / header.getScale().z;
MDLVertex tempVert = new MDLVertex(vertOrigin, 0);
frameVerts[vIndex] = tempVert;
}
frames[frameIndex] = new MDLFrame(MDLFrame.SINGLE_FRAME,
new MDLFrameElement(new MDLVertex(obj.getFrame(frameIndex).getMins(), 0),
new MDLVertex(obj.getFrame(frameIndex).getMaxs(), 0),
"frame",
frameVerts));
}
int numSkins = 1; //TODO: Find out # of skins from OBJ...
header.setNumSkins(numSkins);
header.setSkinWidth(obj.getTextureWidth());
header.setSkinHeight(obj.getTextureHeight());
skins = new MDLSkin[numSkins];
for (int skinIndex = 0; skinIndex < skins.length; skinIndex++)
{
skins[skinIndex] = new MDLSkin(0, obj.getTextureData());
}
//System.out.println("scale: " + header.getScale());
//System.out.println("translate: " + header.getTranslate());
//System.out.println("verts: " + header.getNumVerts());
}
/*
I don't like handing out the array like this. :\
*/
public MDLFrame[] getFrames()
{
return this.frames;
}
public MDLHeader getHeader()
{
return header;
}
public MDLTriangle[] getTriangles()
{
return triangles;
}
public MDLSkin[] getSkins()
{
return skins;
}
public MDLTexCoord[] getTexCoords()
{
return texCoords;
}
public Vec3[] getSimpleTexCoords()
{
Vec3[] texCoordArray = new Vec3[header.getNumTris()];
for (int i = 0; i < texCoordArray.length; i++)
texCoordArray[i] = new Vec3(texCoords[i].getS() / header.getSkinWidth(), texCoords[i].getT() / header.getSkinHeight(), 0.0f);
return texCoordArray;
}
/* @Override
public void drawToOpenGL(int currentFrame)
{
Vec3 org = new Vec3(0f, 0f, 0f);
GL11.glBegin(GL11.GL_TRIANGLES); // Start Drawing
//int triIndex = 1;
for (int triIndex = 0; triIndex < header.getNumTris(); triIndex++)
{
for (int vIndex = 0; vIndex < 3; vIndex++)
{
org = this.frames[currentFrame].getFrameElements()[0].getVertices()[this.getTriangles()[triIndex].getVertexIndices()[vIndex]].getOrigin();
org = (org.scale(header.getScale())).add(header.getTranslate());
// Compute texture coordinates
float s = this.texCoords[this.triangles[triIndex].getVertexIndices()[vIndex]].getS();
float t = this.texCoords[this.triangles[triIndex].getVertexIndices()[vIndex]].getT();
if (!this.triangles[triIndex].isFacingFront() && this.texCoords[this.triangles[triIndex].getVertexIndices()[vIndex]].isOnSeam())
{
s = s + header.getSkinWidth() * 0.5f; // Backface
}
// Scale s and t to range from 0.0 to 1.0
s = (s + 0.5f) / (float) header.getSkinWidth();
t = (t + 0.5f) / (float) header.getSkinHeight();
// Pass texture coordinates to OpenGL
GL11.glTexCoord2f(s, t);
// Normal vector
//GL11.glNormal3f(-0.525731f, 0.000000f, 0.850651f); //glNormal3fv(anorms_table[pvert - > normalIndex]);
GL11.glVertex3f(org.x, org.y, org.z);
}
}
GL11.glEnd(); //stop drawing
}
*/
/*@Override
public void drawVerticesToOpenGL(int currentFrame, ArrayList<Integer> selectedVertices)
{
boolean isVertexSelected = false;
Vec3 org = new Vec3(0f, 0f, 0f);
GL11.glPointSize(4.0f);
GL11.glBegin(GL11.GL_POINTS); // Start Drawing
OpenGL3DView.setDefaultVertexDisplayColour();
for (int triIndex = 0; triIndex < header.getNumTris(); triIndex++)
{
for (int vIndex = 0; vIndex < 3; vIndex++)
{
org = this.getFrames()[currentFrame].getFrameElements()[0].getVertices()[this.getTriangles()[triIndex].getVertexIndices()[vIndex]].getOrigin();
org = org.scale(header.getScale());
org = org.add(header.getTranslate());
if (!selectedVertices.isEmpty())
{
Iterator<Integer> it = selectedVertices.iterator();
while (it.hasNext())
{
Integer selIndex = it.next();
if (selIndex.intValue() == this.triangles[triIndex].getVertexIndices()[vIndex])
{
isVertexSelected = true;
break;
}
}
}
if (isVertexSelected)
OpenGL3DView.setSelectedVertexDisplayColour();
else if (this.texCoords[triangles[triIndex].getVertexIndices()[vIndex]].isOnSeam())
OpenGL3DView.setDefaultVertexOnseamDisplayColour();
else
OpenGL3DView.setDefaultVertexDisplayColour();
GL11.glVertex3f(org.x, org.y, org.z);
//if (isVertexSelected)
//{
isVertexSelected = false;
// OpenGL3DView.setDefaultVertexDisplayColour();
//}
}
}
GL11.glEnd(); //stop drawing
}*/
@Override
public int UploadTextureToOpenGL(int skinIndex)
{
int texID;
int[] skinData = this.getSkins()[skinIndex].getData();
byte[] pixels = new byte[header.getSkinWidth() * header.getSkinHeight() * 3];
/* Convert indexed 8 bits texture to RGB from the colourmap */
for (int i = 0; i < skinData.length; i++)
{
pixels[(i * 3) + 0] = (byte) MDL.colourMap[skinData[i]][0];
pixels[(i * 3) + 1] = (byte) MDL.colourMap[skinData[i]][1];
pixels[(i * 3) + 2] = (byte) MDL.colourMap[skinData[i]][2];
}
ByteBuffer pixelsBuffer = BufferUtils.createByteBuffer(pixels.length);
pixelsBuffer = pixelsBuffer.put(pixels);
pixelsBuffer.rewind();
texID = GL11.glGenTextures(); //generate an id for this open gl texture
GL11.glBindTexture(GL11.GL_TEXTURE_2D, texID); //tell opengl we're working with texID texture.
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, 3, header.getSkinWidth(), header.getSkinHeight(), 0, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, pixelsBuffer);
return texID;
}
@Override
public void setTexture(PCX pcxImage)
{
JOptionPane.showMessageDialog(null, "Texture loading on MDLs not supported yet.");
//throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean getHasTexture()
{
return this.header.getNumSkins() > 0;
}
@Override
public int[] getTextureData()
{
return this.skins[0].getData();
}
@Override
public int getTextureWidth()
{
return this.header.getSkinWidth();
}
@Override
public int getTextureHeight()
{
return this.header.getSkinHeight();
}
@Override
public void exportMDL(String _filename)
{
int sizeEstimate = MDL_HEADER_SIZE; //start with the header size.
//TODO: REMEMBER, skin groups have a DIFFERENT sized struct!!! If group == 1, you'll have to calculate differently
sizeEstimate += this.header.getNumSkins() * 4; //each skin has a 4 byte int
//add in bytes for each skin (width * height)
sizeEstimate += this.header.getNumSkins() * this.header.getSkinWidth() * this.header.getSkinHeight();
//add in size for texcoords
sizeEstimate += this.header.getNumVerts() * (4 * 3); //mdl_texcoord_t is 3 4byte ints * number of verts
sizeEstimate += this.header.getNumTris() * (4 * 4); //mdl_triangle_t is 1 4byte int + array of 3 4byte ints (16 bytes total)
sizeEstimate += this.header.getNumFrames() * (4 + 4 + 4 + 16 + (this.header.getNumVerts() * 4));
//long/int + struct mdl_vertex_t + struct mdl_vertex_t + char[16] + struct mdl_vertex_t * numVerts ALL * numFrames
System.out.println("Estimated file size: " + sizeEstimate + " bytes.");
ByteBuffer buffer = ByteBuffer.allocate(sizeEstimate);
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.putInt(this.header.getIdent());
buffer.putInt(this.header.getVersion());
buffer.putFloat(this.header.getScale().x);
buffer.putFloat(this.header.getScale().y);
buffer.putFloat(this.header.getScale().z);
buffer.putFloat(this.header.getTranslate().x);
buffer.putFloat(this.header.getTranslate().y);
buffer.putFloat(this.header.getTranslate().z);
buffer.putFloat(this.header.getBoundingRadius());
buffer.putFloat(this.header.getEyePosition().x);
buffer.putFloat(this.header.getEyePosition().y);
buffer.putFloat(this.header.getEyePosition().z);
buffer.putInt(this.header.getNumSkins());
buffer.putInt(this.header.getSkinWidth());
buffer.putInt(this.header.getSkinHeight());
buffer.putInt(this.header.getNumVerts());
buffer.putInt(this.header.getNumTris());
buffer.putInt(this.header.getNumFrames());
buffer.putInt(this.header.getSyncType());
buffer.putInt(this.header.getFlags());
buffer.putFloat(this.header.getSize());
for (int i = 0; i < this.header.getNumSkins(); i++) //write skin data
{
buffer.putInt(this.getSkins()[i].getGroup());
for (int j = 0; j < this.getSkins()[i].getData().length; j++)
buffer.put((byte) this.getSkins()[i].getData()[j]); //cast the fake ints (unsigned bytes) back to bytes.
}
for (int i = 0; i < this.header.getNumVerts(); i++)
{
buffer.putInt(this.texCoords[i].getOnseam());
buffer.putInt((int) Math.round(this.texCoords[i].getS()));
buffer.putInt((int) Math.round(this.texCoords[i].getT()));
}
for (int i = 0; i < this.header.getNumTris(); i++)
{
buffer.putInt(this.triangles[i].getFacesFront());
buffer.putInt(this.triangles[i].getVertexIndices()[0]);
buffer.putInt(this.triangles[i].getVertexIndices()[1]);
buffer.putInt(this.triangles[i].getVertexIndices()[2]);
}
//sizeEstimate += this.header.getNumFrames() * (4 + 4 + 4 + 16 + (this.header.getNumVerts() * 4));
for (int i = 0; i < this.header.getNumFrames(); i++)
{
buffer.putInt(this.frames[i].getType());
buffer.put((byte) this.frames[i].getFrameElements()[0].getMins().getOrigin().x);
buffer.put((byte) this.frames[i].getFrameElements()[0].getMins().getOrigin().y);
buffer.put((byte) this.frames[i].getFrameElements()[0].getMins().getOrigin().z);
buffer.put((byte) 0); //normal index which is unused
buffer.put((byte) this.frames[i].getFrameElements()[0].getMaxs().getOrigin().x);
buffer.put((byte) this.frames[i].getFrameElements()[0].getMaxs().getOrigin().y);
buffer.put((byte) this.frames[i].getFrameElements()[0].getMaxs().getOrigin().z);
buffer.put((byte) 0); //normal index which is unused
String name = this.frames[i].getFrameElements()[0].getName();
for (int j = 0; j < 16; j++)
{
if (j >= name.length())
buffer.put((byte) '\0'); //let's be cool and zero out the unused chars.
else
buffer.put((byte) name.charAt(j)); //FFS, chars are 4 bytes in java. :(
}
for (int j = 0; j < this.header.getNumVerts(); j++)
{
buffer.put((byte) this.frames[i].getFrameElements()[0].getVertices()[j].getOrigin().x);
buffer.put((byte) this.frames[i].getFrameElements()[0].getVertices()[j].getOrigin().y);
buffer.put((byte) this.frames[i].getFrameElements()[0].getVertices()[j].getOrigin().z);
buffer.put((byte) this.frames[i].getFrameElements()[0].getVertices()[j].getNormalIndex());
}
}
byte[] bytes = buffer.array();
File outputFile = new File(_filename);
FileOutputStream outputStream = null;
try
{
outputStream = new FileOutputStream(outputFile);
outputStream.write(bytes);
}
catch (Exception ex)
{
Logger.getLogger(MDL.class.getName()).log(Level.SEVERE, null, ex);
throw new RuntimeException(ex.getMessage());
}
finally
{
try
{
outputStream.close();
}
catch (IOException ex)
{
Logger.getLogger(MDL.class.getName()).log(Level.SEVERE, null, ex);
throw new RuntimeException(ex.getMessage());
}
}
}
@Override
public int getFrameIndexFromNameIndex(int selectedIndex)
{
return selectedIndex;
}
@Override
public float[][] getScalarUVCoordsArray()
{
float[][] UVArray = new float[this.texCoords.length][3];
for (int i = 0; i < UVArray.length; i++)
{
UVArray[i][0] = (float) this.texCoords[i].getS() / this.header.getSkinWidth();
UVArray[i][1] = (float) this.texCoords[i].getT() / this.header.getSkinHeight();
UVArray[i][2] = this.texCoords[i].getOnseam(); //2 = onseam values
}
return UVArray;
}
@Override
public int[][][] getUV_TriRelationArray()
{
int[][][] triArray = new int[this.triangles.length][3][3];
for (int triIndex = 0; triIndex < triArray.length; triIndex++)
{
for (int vIndex = 0; vIndex < 3; vIndex++) //MDL has 1:1 relationship between verts and skin verts.
{
triArray[triIndex][vIndex][0] = triArray[triIndex][vIndex][1] = triangles[triIndex].getVertexIndices()[vIndex];
triArray[triIndex][vIndex][2] = triangles[triIndex].getFacesFront(); //2 = front facing tri value
}
}
return triArray;
}
@Override
public void moveUVCoordBy(int index, float deltaX, float deltaY, int zoom)
{
deltaX = deltaX / zoom;
deltaY = deltaY / zoom;
texCoords[index].setS(texCoords[index].getS() + deltaX);
texCoords[index].setT(texCoords[index].getT() + deltaY);
}
@Override
public String[] getFrameNames()
{
MDLFrameElement[] frameElements;
int totalFrames = 0;
for (int i = 0; i < frames.length; i++)
totalFrames = totalFrames + frames[i].getFrameElements().length;
ArrayList<String> frameNames = new ArrayList();
for (int i = 0; i < frames.length; i++)
{
frameElements = frames[i].getFrameElements();
for (int j = 0; j < frameElements.length; j++)
frameNames.add(frameElements[j].getName());
}
return frameNames.toArray(new String[frameNames.size()]);
}
@Override
public Vec3[] getVertices(int frame)
{
MDLVertex[] vertices = this.frames[frame].getFrameElements()[0].getVertices();
Vec3[] vOrigins = new Vec3[vertices.length];
for (int vIndex = 0; vIndex < vertices.length; vIndex++)
{
Vec3 vOrigin = vertices[vIndex].getOrigin();
vOrigin = vOrigin.scale(header.getScale()); //pre-scale vertex positions.
vOrigin = vOrigin.add(header.getTranslate());
vOrigins[vIndex] = vOrigin;
}
return vOrigins;
}
}