/*******************************************************************************
* Copyright (C) 2013 JMaNGOS <http://jmangos.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package org.jmangos.tools.m2;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* @author MinimaJack
*
*/
/**
* @author MinimaJack
*
*/
/**
* @author MinimaJack
*
*/
/**
* @author MinimaJack
*
*/
/**
* @author MinimaJack
*
*/
public final class M2 {
/**
* Offsets
*/
private final Offsets offsets = new Offsets();
/**
* Other data
*/
private final Other other = new Other();
/**
* Data
*/
private final Data data = new Data();
/**
* Lengths
*/
private final Lengths lengths = new Lengths();
/**
* hidden constructor
*/
private M2() {
}
/**
* @param bb
* - ByteBuffer
* @return M2
*/
public static M2 read(final ByteBuffer bb) {
bb.order(ByteOrder.LITTLE_ENDIAN); // format is in little endian, ensure
// the buffer is too
final M2 result = new M2();
bb.get(result.other.getMagic());
result.other.setVersion(bb.getInt());
result.lengths.setlName(bb.getInt());
result.offsets.setOfsName(bb.getInt());
result.other.setGlobalModelFlags(bb.getInt());
result.lengths.setnGlobalSequences(bb.getInt());
result.offsets.setOfsGlobalSequences(bb.getInt());
result.lengths.setnAnimations(bb.getInt());
result.offsets.setOfsAnimations(bb.getInt());
result.lengths.setnAnimationLookup(bb.getInt());
result.offsets.setOfsAnimationLookup(bb.getInt());
result.lengths.setnBones(bb.getInt());
result.offsets.setOfsBones(bb.getInt());
result.lengths.setnKeyBoneLookup(bb.getInt());
result.offsets.setOfsKeyBoneLookup(bb.getInt());
result.lengths.setnVertices(bb.getInt());
result.offsets.setOfsVertices(bb.getInt());
result.lengths.setnViews(bb.getInt());
result.lengths.setnColors(bb.getInt());
result.offsets.setOfsColors(bb.getInt());
result.lengths.setnTextures(bb.getInt());
result.offsets.setOfsTextures(bb.getInt());
result.lengths.setnTransparency(bb.getInt());
result.offsets.setOfsTransparency(bb.getInt());
result.lengths.setnTextureAnimations(bb.getInt());
result.offsets.setOfsTextureAnimations(bb.getInt());
result.lengths.setnTexReplace(bb.getInt());
result.offsets.setOfsTexReplace(bb.getInt());
result.lengths.setnRenderFlags(bb.getInt());
result.offsets.setOfsRenderFlags(bb.getInt());
result.lengths.setnBoneLookupTable(bb.getInt());
result.offsets.setOfsBoneLookupTable(bb.getInt());
result.lengths.setnTexLookup(bb.getInt());
result.offsets.setOfsTexLookup(bb.getInt());
result.lengths.setnTexUnits(bb.getInt());
result.offsets.setOfsTexUnits(bb.getInt());
result.lengths.setnTransLookup(bb.getInt());
result.offsets.setOfsTransLookup(bb.getInt());
result.lengths.setnTexAnimLookup(bb.getInt());
for (int index = 0; index < result.other.getTheFloats().length; index++) {
result.other.getTheFloats()[index] = bb.getFloat();
}
result.lengths.setnBoundingTringles(bb.getInt());
result.offsets.setOfsBoundTriangles(bb.getInt());
result.lengths.setnBoundingVertices(bb.getInt());
result.offsets.setOfsBoundingVertices(bb.getInt());
result.lengths.setnBoundingNormals(bb.getInt());
result.offsets.setOfsBoundingNormals(bb.getInt());
result.lengths.setnAttachments(bb.getInt());
result.offsets.setOfsAttachments(bb.getInt());
result.lengths.setnAttachLookup(bb.getInt());
result.offsets.setOfsAttachLookup(bb.getInt());
result.lengths.setnAttachments2(bb.getInt());
result.offsets.setOfsAttachments2(bb.getInt());
result.lengths.setnLights(bb.getInt());
result.offsets.setOfsLights(bb.getInt());
result.lengths.setnCameras(bb.getInt());
result.offsets.setOfsCameras(bb.getInt());
result.lengths.setnCameraLookup(bb.getInt());
result.offsets.setOfsCameraLookup(bb.getInt());
result.lengths.setnRibbonEmitters(bb.getInt());
result.offsets.setOfsRibbonEmitters(bb.getInt());
result.lengths.setnParticleEmitters(bb.getInt());
result.offsets.setOfsParticleEmitters(bb.getInt());
result.lengths.setnUnknown(bb.getInt());
result.offsets.setOfsUnknown(bb.getInt());
readData(result, bb);
return result;
}
/**
*
* @return data vertexes
*/
public Vertex[] getVertexes() {
return this.data.getVertexes();
}
/**
*
* @param i
* - vertex index
* @return data vertex by index i
*/
public Vertex getVertex(final int i) {
return this.data.getVertexes()[i];
}
/**
*
* @return vertexes count
*/
public int getVertexesCount() {
return this.data.getVertexes().length;
}
/**
* Read m2 from file
*
* @param f
* - file with M2
* @return M2 from given File or null if file not exist.
*/
public static M2 read(final File f) {
if (!f.exists()) {
return null;
}
FileInputStream fis = null;
final ByteBuffer bb = ByteBuffer.allocate((int) f.length());
M2 result = null;
try {
fis = new FileInputStream(f);
fis.getChannel().read(bb);
bb.rewind();
result = read(bb);
} catch (final FileNotFoundException e) {
e.printStackTrace();
} catch (final IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (final IOException e) {
e.printStackTrace();
}
}
}
return result;
}
/**
* read m2 data
*
* @param m2Object
* - m2 object
* @param bb
* - ByteBuffer
*/
protected static void readData(final M2 m2Object, final ByteBuffer bb) {
bb.position(m2Object.offsets.getOfsName());
m2Object.data.setName(ByteBufferUtil.readString(bb, m2Object.lengths.getlName()));
bb.position(m2Object.offsets.getOfsGlobalSequences());
m2Object.data.setGlobalSequences(ByteBufferUtil.readInts(bb,
m2Object.lengths.getnGlobalSequences()));
bb.position(m2Object.offsets.getOfsAnimationLookup());
m2Object.data.setAnimationLookups(ByteBufferUtil.readShorts(bb,
m2Object.lengths.getnAnimationLookup()));
bb.position(m2Object.offsets.getOfsRenderFlags());
m2Object.data.setRenderFlags(ByteBufferUtil.readInts(bb, m2Object.lengths.getnRenderFlags()));
bb.position(m2Object.offsets.getOfsKeyBoneLookup());
m2Object.data.setKeyBoneLookupTable(ByteBufferUtil.readShorts(bb,
m2Object.lengths.getnKeyBoneLookup()));
bb.position(m2Object.offsets.getOfsBoneLookupTable());
m2Object.data.setBoneLookupTable(ByteBufferUtil.readShorts(bb,
m2Object.lengths.getnBoneLookupTable()));
bb.position(m2Object.offsets.getOfsVertices());
m2Object.data.setVertexes(new Vertex[m2Object.lengths.getnVertices()]);
for (int index = 0; index < m2Object.lengths.getnVertices(); index++) {
m2Object.data.getVertexes()[index] = Vertex.read(bb);
}
bb.position(m2Object.offsets.getOfsAnimations());
m2Object.data.setAnimations(new AnimationSequence[m2Object.lengths.getnAnimations()]);
for (int index = 0; index < m2Object.lengths.getnAnimations(); index++) {
m2Object.data.getAnimations()[index] = AnimationSequence.read(bb);
}
bb.position(m2Object.offsets.getOfsTextures());
m2Object.data.setTextures(new Textures[m2Object.lengths.getnTextures()]);
for (int index = 0; index < m2Object.lengths.getnTextures(); index++) {
m2Object.data.getTextures()[index] = Textures.read(bb);
}
for (int index = 0; index < m2Object.lengths.getnTextures(); index++) {
if (m2Object.data.getTextures()[index].getType() == 0) {
bb.position(m2Object.data.getTextures()[index].getOfsFilename());
m2Object.data.getTextures()[index].setFileName(ByteBufferUtil.readString(bb,
m2Object.data.getTextures()[index].getLenFilename()));
}
}
}
}