* Add support for WoTLK M2 files
This brought along some restructuring of the Loader code to make it more readable
This commit is contained in:
parent
1fdcaa691b
commit
726faeff87
@ -1,4 +1,4 @@
|
|||||||
#define _DEBUG 1
|
// #define _DEBUG 1
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "MemoryDataHolder.h"
|
#include "MemoryDataHolder.h"
|
||||||
#include "MemoryInterface.h"
|
#include "MemoryInterface.h"
|
||||||
@ -66,16 +66,16 @@ void CM2MeshFileLoader::ReadVertices()
|
|||||||
M2MVertices.clear();
|
M2MVertices.clear();
|
||||||
|
|
||||||
ModelVertex tempM2MVert;
|
ModelVertex tempM2MVert;
|
||||||
MeshFile->seek(header.ofsVertices);
|
MeshFile->seek(header.Vertices.ofs);
|
||||||
|
|
||||||
for(u32 i =0;i<header.nVertices;i++)
|
for(u32 i =0;i<header.Vertices.num;i++)
|
||||||
{
|
{
|
||||||
MeshFile->read(&tempM2MVert,sizeof(ModelVertex));
|
MeshFile->read(&tempM2MVert,sizeof(ModelVertex));
|
||||||
tempM2MVert.pos = fixCoordSystem(tempM2MVert.pos);
|
tempM2MVert.pos = fixCoordSystem(tempM2MVert.pos);
|
||||||
tempM2MVert.normal = fixCoordSystem(tempM2MVert.normal);
|
tempM2MVert.normal = fixCoordSystem(tempM2MVert.normal);
|
||||||
M2MVertices.push_back(tempM2MVert);
|
M2MVertices.push_back(tempM2MVert);
|
||||||
}
|
}
|
||||||
DEBUG(logdebug("Read %u/%u Vertices",M2MVertices.size(),header.nVertices));
|
DEBUG(logdebug("Read %u/%u Vertices",M2MVertices.size(),header.Vertices.num));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CM2MeshFileLoader::ReadViewData(io::IReadFile* file)
|
void CM2MeshFileLoader::ReadViewData(io::IReadFile* file)
|
||||||
@ -85,40 +85,40 @@ void CM2MeshFileLoader::ReadViewData(io::IReadFile* file)
|
|||||||
M2MIndices.clear();
|
M2MIndices.clear();
|
||||||
|
|
||||||
u16 tempM2Index;
|
u16 tempM2Index;
|
||||||
file->seek(currentView.ofsIndex);
|
file->seek(currentView.Index.ofs);
|
||||||
for(u32 i =0;i<currentView.nIndex;i++)
|
for(u32 i =0;i<currentView.Index.num;i++)
|
||||||
{
|
{
|
||||||
file->read(&tempM2Index,sizeof(u16));
|
file->read(&tempM2Index,sizeof(u16));
|
||||||
M2MIndices.push_back(tempM2Index);
|
M2MIndices.push_back(tempM2Index);
|
||||||
}
|
}
|
||||||
DEBUG(logdebug("Read %u/%u Indices",M2MIndices.size(),currentView.nIndex));
|
DEBUG(logdebug("Read %u/%u Indices",M2MIndices.size(),currentView.Index.num));
|
||||||
|
|
||||||
//Triangles. Data Points point to the Vertex Indices, not the vertices themself. 3 Points = 1 Triangle, Local to View 0
|
//Triangles. Data Points point to the Vertex Indices, not the vertices themself. 3 Points = 1 Triangle, Local to View 0
|
||||||
if(M2MTriangles.size()>0)
|
if(M2MTriangles.size()>0)
|
||||||
M2MTriangles.clear();
|
M2MTriangles.clear();
|
||||||
|
|
||||||
u16 tempM2Triangle;
|
u16 tempM2Triangle;
|
||||||
file->seek(currentView.ofsTris);
|
file->seek(currentView.Triangle.ofs);
|
||||||
for(u32 i =0;i<currentView.nTris;i++)
|
for(u32 i =0;i<currentView.Triangle.num;i++)
|
||||||
{
|
{
|
||||||
file->read(&tempM2Triangle,sizeof(u16));
|
file->read(&tempM2Triangle,sizeof(u16));
|
||||||
M2MTriangles.push_back(tempM2Triangle);
|
M2MTriangles.push_back(tempM2Triangle);
|
||||||
}
|
}
|
||||||
DEBUG(logdebug("Read %u/%u Triangles",M2MTriangles.size(),currentView.nTris));
|
DEBUG(logdebug("Read %u/%u Triangles",M2MTriangles.size(),currentView.Triangle.num));
|
||||||
//Submeshes, Local to View 0
|
//Submeshes, Local to View 0
|
||||||
if(M2MSubmeshes.size()>0)
|
if(M2MSubmeshes.size()>0)
|
||||||
M2MSubmeshes.clear();
|
M2MSubmeshes.clear();
|
||||||
|
|
||||||
ModelViewSubmesh tempM2Submesh;
|
ModelViewSubmesh tempM2Submesh;
|
||||||
file->seek(currentView.ofsSub);
|
file->seek(currentView.Submesh.ofs);
|
||||||
for(u32 i =0;i<currentView.nSub;i++)
|
for(u32 i =0;i<currentView.Submesh.num;i++)
|
||||||
{
|
{
|
||||||
file->read(&tempM2Submesh,sizeof(ModelViewSubmesh)-(header.version==0x100?16:0));
|
file->read(&tempM2Submesh,sizeof(ModelViewSubmesh)-(header.version==0x100?16:0));
|
||||||
M2MSubmeshes.push_back(tempM2Submesh);
|
M2MSubmeshes.push_back(tempM2Submesh);
|
||||||
DEBUG(logdebug("Submesh %u nBone: %u ofsBone: %u",i,tempM2Submesh.nBone, tempM2Submesh.ofsBone));
|
DEBUG(logdebug("Submesh %u nBone: %u ofsBone: %u",i,tempM2Submesh.nBone, tempM2Submesh.ofsBone));
|
||||||
// std::cout<< "Submesh " <<i<<" ID "<<tempM2Submesh.meshpartId<<" starts at V/T "<<tempM2Submesh.ofsVertex<<"/"<<tempM2Submesh.ofsTris<<" and has "<<tempM2Submesh.nVertex<<"/"<<tempM2Submesh.nTris<<" V/T\n";
|
// std::cout<< "Submesh " <<i<<" ID "<<tempM2Submesh.meshpartId<<" starts at V/T "<<tempM2Submesh.ofsVertex<<"/"<<tempM2Submesh.ofsTris<<" and has "<<tempM2Submesh.nVertex<<"/"<<tempM2Submesh.nTris<<" V/T\n";
|
||||||
}
|
}
|
||||||
DEBUG(logdebug("Read %u/%u Submeshes",M2MSubmeshes.size(),currentView.nSub));
|
DEBUG(logdebug("Read %u/%u Submeshes",M2MSubmeshes.size(),currentView.Submesh.num));
|
||||||
|
|
||||||
//Texture units. Local to view 0
|
//Texture units. Local to view 0
|
||||||
TextureUnit tempM2TexUnit;
|
TextureUnit tempM2TexUnit;
|
||||||
@ -126,8 +126,8 @@ void CM2MeshFileLoader::ReadViewData(io::IReadFile* file)
|
|||||||
{
|
{
|
||||||
M2MTextureUnit.clear();
|
M2MTextureUnit.clear();
|
||||||
}
|
}
|
||||||
file->seek(currentView.ofsTex);
|
file->seek(currentView.Tex.ofs);
|
||||||
for(u32 i=0;i<currentView.nTex;i++)
|
for(u32 i=0;i<currentView.Tex.num;i++)
|
||||||
{
|
{
|
||||||
file->read(&tempM2TexUnit,sizeof(TextureUnit));
|
file->read(&tempM2TexUnit,sizeof(TextureUnit));
|
||||||
M2MTextureUnit.push_back(tempM2TexUnit);
|
M2MTextureUnit.push_back(tempM2TexUnit);
|
||||||
@ -137,134 +137,77 @@ void CM2MeshFileLoader::ReadViewData(io::IReadFile* file)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CM2MeshFileLoader::ReadAnimationData()
|
void CM2MeshFileLoader::ReadBones()
|
||||||
{
|
{
|
||||||
|
|
||||||
//Global Sequences. This is global data
|
|
||||||
u32 tempGlobalSeq;
|
|
||||||
if(!M2MGlobalSequences.empty())
|
|
||||||
{
|
|
||||||
M2MGlobalSequences.clear();
|
|
||||||
}
|
|
||||||
MeshFile->seek(header.ofsGlobalSequences);
|
|
||||||
for(u32 i=0;i<header.nGlobalSequences;i++)
|
|
||||||
{
|
|
||||||
MeshFile->read(&tempGlobalSeq,sizeof(u32));
|
|
||||||
M2MGlobalSequences.push_back(tempGlobalSeq);
|
|
||||||
DEBUG(logdebug("Global Sequence %u End %u",i,tempGlobalSeq));
|
|
||||||
}
|
|
||||||
DEBUG(logdebug("Read %u Global Sequence entries",M2MGlobalSequences.size()));
|
|
||||||
|
|
||||||
//BoneLookupTable. This is global data
|
|
||||||
u16 tempBoneLookup;
|
|
||||||
if(!M2MBoneLookupTable.empty())
|
|
||||||
{
|
|
||||||
M2MBoneLookupTable.clear();
|
|
||||||
}
|
|
||||||
MeshFile->seek(header.ofsBoneLookupTable);
|
|
||||||
for(u32 i=0;i<header.nBoneLookupTable;i++)
|
|
||||||
{
|
|
||||||
MeshFile->read(&tempBoneLookup,sizeof(u16));
|
|
||||||
M2MBoneLookupTable.push_back(tempBoneLookup);
|
|
||||||
DEBUG(logdebug("BoneLookupTable %u Value %u",i,tempBoneLookup));
|
|
||||||
}
|
|
||||||
DEBUG(logdebug("Read %u BoneLookupTable entries",M2MBoneLookupTable.size()));
|
|
||||||
|
|
||||||
//SkeleBoneLookupTable. This is global data
|
|
||||||
u16 tempSkeleBoneLookup;
|
|
||||||
if(!M2MSkeleBoneLookupTable.empty())
|
|
||||||
{
|
|
||||||
M2MSkeleBoneLookupTable.clear();
|
|
||||||
}
|
|
||||||
MeshFile->seek(header.ofsSkelBoneLookup);
|
|
||||||
for(u32 i=0;i<header.nSkelBoneLookup;i++)
|
|
||||||
{
|
|
||||||
MeshFile->read(&tempSkeleBoneLookup,sizeof(u16));
|
|
||||||
M2MSkeleBoneLookupTable.push_back(tempSkeleBoneLookup);
|
|
||||||
DEBUG(logdebug("SkeleBoneLookupTable %u Value %u",i,tempSkeleBoneLookup));
|
|
||||||
}
|
|
||||||
DEBUG(logdebug("Read %u SkeleBoneLookupTable entries",M2MSkeleBoneLookupTable.size()));
|
|
||||||
|
|
||||||
//Animations. This is global data
|
|
||||||
Animation tempAnimation;
|
|
||||||
if(!M2MAnimations.empty())
|
|
||||||
{
|
|
||||||
M2MAnimations.clear();
|
|
||||||
}
|
|
||||||
MeshFile->seek(header.ofsAnimations);
|
|
||||||
for(u32 i=0;i<header.nAnimations;i++)
|
|
||||||
{
|
|
||||||
MeshFile->read(&tempAnimation,sizeof(Animation));
|
|
||||||
M2MAnimations.push_back(tempAnimation);
|
|
||||||
DEBUG(logdebug("Animation %u Id %u Start %u End %u",i,tempAnimation.animationID,tempAnimation.start,tempAnimation.end));
|
|
||||||
}
|
|
||||||
DEBUG(logdebug("Read %u Animations",M2MAnimations.size()));
|
|
||||||
|
|
||||||
//Bones. This is global data
|
//Bones. This is global data
|
||||||
Bone tempBone;
|
Bone tempBone;
|
||||||
if(!M2MBones.empty())
|
if(!M2MBones.empty())
|
||||||
{
|
{
|
||||||
M2MBones.clear();
|
M2MBones.clear();
|
||||||
}
|
}
|
||||||
MeshFile->seek(header.ofsBones);
|
MeshFile->seek(header.Bones.ofs);
|
||||||
for(u32 i=0;i<header.nBones;i++)
|
for(u32 i=0;i<header.Bones.num;i++)
|
||||||
{
|
{
|
||||||
MeshFile->read(&tempBone,12+(header.version==0x100?0:4));
|
MeshFile->read(&tempBone,12+(header.version==0x100?0:4));
|
||||||
|
|
||||||
MeshFile->read(&tempBone.translation.header,sizeof(AnimBlockHead));
|
MeshFile->read(&tempBone.translation.header,sizeof(AnimBlockHead));
|
||||||
MeshFile->read(&tempBone.rotation.header,sizeof(AnimBlockHead));
|
MeshFile->read(&tempBone.rotation.header,sizeof(AnimBlockHead));
|
||||||
MeshFile->read(&tempBone.scaling.header,sizeof(AnimBlockHead));
|
MeshFile->read(&tempBone.scaling.header,sizeof(AnimBlockHead));
|
||||||
|
|
||||||
MeshFile->read(&tempBone.PivotPoint,sizeof(core::vector3df));
|
MeshFile->read(&tempBone.PivotPoint,sizeof(core::vector3df));
|
||||||
tempBone.PivotPoint=fixCoordSystem(tempBone.PivotPoint);
|
tempBone.PivotPoint=fixCoordSystem(tempBone.PivotPoint);
|
||||||
M2MBones.push_back(tempBone);
|
M2MBones.push_back(tempBone);
|
||||||
DEBUG(logdebug("Bone %u Parent %u PP %f %f %f",i,tempBone.parentBone,tempBone.PivotPoint.X,tempBone.PivotPoint.Y,tempBone.PivotPoint.Z));
|
DEBUG(logdebug("Bone %u Parent %u PP %f %f %f Flags %X",i,tempBone.parentBone,tempBone.PivotPoint.X,tempBone.PivotPoint.Y,tempBone.PivotPoint.Z, tempBone.flags));
|
||||||
}
|
}
|
||||||
//Fill in values referenced in Bones. local to each bone
|
//Fill in values referenced in Bones. local to each bone
|
||||||
//Interpolation Ranges are not used
|
//Interpolation Ranges are not used
|
||||||
u32 tempBoneTS;
|
u32 tempBoneTS;
|
||||||
|
numofs tempBoneNumOfs;
|
||||||
float tempBoneValue;
|
float tempBoneValue;
|
||||||
for(u32 i=0; i<M2MBones.size(); i++)
|
for(u32 i=0; i<M2MBones.size(); i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
if(M2MBones[i].translation.header.nTimeStamp>0)
|
if(M2MBones[i].translation.header.TimeStamp.num>0)
|
||||||
{
|
{
|
||||||
MeshFile->seek(M2MBones[i].translation.header.ofsTimeStamp);
|
MeshFile->seek(M2MBones[i].translation.header.TimeStamp.ofs);
|
||||||
for(u32 j=0; j<M2MBones[i].translation.header.nTimeStamp;j++)
|
for(u32 j=0; j<M2MBones[i].translation.header.TimeStamp.num;j++)
|
||||||
{
|
{
|
||||||
MeshFile->read(&tempBoneTS, sizeof(u32));
|
MeshFile->read(&tempBoneTS, sizeof(u32));
|
||||||
M2MBones[i].translation.timestamps.push_back(tempBoneTS);
|
M2MBones[i].translation.timestamps.push_back(tempBoneTS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(M2MBones[i].rotation.header.nTimeStamp>0)
|
if(M2MBones[i].rotation.header.TimeStamp.num>0)
|
||||||
{
|
{
|
||||||
MeshFile->seek(M2MBones[i].rotation.header.ofsTimeStamp);
|
MeshFile->seek(M2MBones[i].rotation.header.TimeStamp.ofs);
|
||||||
for(u32 j=0; j<M2MBones[i].rotation.header.nTimeStamp;j++)
|
for(u32 j=0; j<M2MBones[i].rotation.header.TimeStamp.num;j++)
|
||||||
{
|
{
|
||||||
MeshFile->read(&tempBoneTS, sizeof(u32));
|
MeshFile->read(&tempBoneTS, sizeof(u32));
|
||||||
M2MBones[i].rotation.timestamps.push_back(tempBoneTS);
|
M2MBones[i].rotation.timestamps.push_back(tempBoneTS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(M2MBones[i].scaling.header.nTimeStamp>0)
|
if(M2MBones[i].scaling.header.TimeStamp.num>0)
|
||||||
{
|
{
|
||||||
MeshFile->seek(M2MBones[i].scaling.header.ofsTimeStamp);
|
MeshFile->seek(M2MBones[i].scaling.header.TimeStamp.ofs);
|
||||||
for(u32 j=0; j<M2MBones[i].scaling.header.nTimeStamp;j++)
|
for(u32 j=0; j<M2MBones[i].scaling.header.TimeStamp.num;j++)
|
||||||
{
|
{
|
||||||
MeshFile->read(&tempBoneTS, sizeof(u32));
|
MeshFile->read(&tempBoneTS, sizeof(u32));
|
||||||
M2MBones[i].scaling.timestamps.push_back(tempBoneTS);
|
M2MBones[i].scaling.timestamps.push_back(tempBoneTS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(M2MBones[i].translation.header.nValues>0)
|
if(M2MBones[i].translation.header.Values.num>0)
|
||||||
{
|
{
|
||||||
MeshFile->seek(M2MBones[i].translation.header.ofsValues);
|
MeshFile->seek(M2MBones[i].translation.header.Values.ofs);
|
||||||
for(u32 j=0; j<M2MBones[i].translation.header.nValues*3;j++)
|
for(u32 j=0; j<M2MBones[i].translation.header.Values.num*3;j++)
|
||||||
{
|
{
|
||||||
MeshFile->read(&tempBoneValue, sizeof(float));
|
MeshFile->read(&tempBoneValue, sizeof(float));
|
||||||
M2MBones[i].translation.values.push_back(tempBoneValue);
|
M2MBones[i].translation.values.push_back(tempBoneValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(M2MBones[i].rotation.header.nValues>0)
|
if(M2MBones[i].rotation.header.Values.num>0)
|
||||||
{
|
{
|
||||||
MeshFile->seek(M2MBones[i].rotation.header.ofsValues);
|
MeshFile->seek(M2MBones[i].rotation.header.Values.ofs);
|
||||||
for(u32 j=0; j<M2MBones[i].rotation.header.nValues*4;j++)
|
for(u32 j=0; j<M2MBones[i].rotation.header.Values.num*4;j++)
|
||||||
{
|
{
|
||||||
if(header.version>=0x104)
|
if(header.version>=0x104)
|
||||||
{
|
{
|
||||||
@ -280,10 +223,10 @@ for(u32 i=0; i<M2MBones.size(); i++)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(M2MBones[i].scaling.header.nValues>0)
|
if(M2MBones[i].scaling.header.Values.num>0)
|
||||||
{
|
{
|
||||||
MeshFile->seek(M2MBones[i].scaling.header.ofsValues);
|
MeshFile->seek(M2MBones[i].scaling.header.Values.ofs);
|
||||||
for(u32 j=0; j<M2MBones[i].scaling.header.nValues*3;j++)
|
for(u32 j=0; j<M2MBones[i].scaling.header.Values.num*3;j++)
|
||||||
{
|
{
|
||||||
MeshFile->read(&tempBoneValue, sizeof(float));
|
MeshFile->read(&tempBoneValue, sizeof(float));
|
||||||
M2MBones[i].scaling.values.push_back(tempBoneValue);
|
M2MBones[i].scaling.values.push_back(tempBoneValue);
|
||||||
@ -291,10 +234,293 @@ for(u32 i=0; i<M2MBones.size(); i++)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG(logdebug("Read %u Bones",M2MBones.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CM2MeshFileLoader::ReadBonesWOTLK()
|
||||||
|
{
|
||||||
|
//Bones. This is global data
|
||||||
|
Bone tempBone;
|
||||||
|
if(!M2MBones.empty())
|
||||||
|
{
|
||||||
|
M2MBones.clear();
|
||||||
|
}
|
||||||
|
MeshFile->seek(header.Bones.ofs);
|
||||||
|
for(u32 i=0;i<header.Bones.num;i++)
|
||||||
|
{
|
||||||
|
MeshFile->read(&tempBone,16);
|
||||||
|
//Skip Interpolation Ranges
|
||||||
|
MeshFile->read(&tempBone.translation.header,4);
|
||||||
|
MeshFile->read(&tempBone.translation.header.TimeStamp,sizeof(numofs));
|
||||||
|
MeshFile->read(&tempBone.translation.header.Values,sizeof(numofs));
|
||||||
|
MeshFile->read(&tempBone.rotation.header,4);
|
||||||
|
MeshFile->read(&tempBone.rotation.header.TimeStamp,sizeof(numofs));
|
||||||
|
MeshFile->read(&tempBone.rotation.header.Values,sizeof(numofs));
|
||||||
|
MeshFile->read(&tempBone.scaling.header,4);
|
||||||
|
MeshFile->read(&tempBone.scaling.header.TimeStamp,sizeof(numofs));
|
||||||
|
MeshFile->read(&tempBone.scaling.header.Values,sizeof(numofs));
|
||||||
|
|
||||||
|
MeshFile->read(&tempBone.PivotPoint,sizeof(core::vector3df));
|
||||||
|
tempBone.PivotPoint=fixCoordSystem(tempBone.PivotPoint);
|
||||||
|
M2MBones.push_back(tempBone);
|
||||||
|
DEBUG(logdebug("Bone %u Parent %u PP %f %f %f Flags %X",i,tempBone.parentBone,tempBone.PivotPoint.X,tempBone.PivotPoint.Y,tempBone.PivotPoint.Z, tempBone.flags));
|
||||||
|
}
|
||||||
|
//Fill in values referenced in Bones. local to each bone
|
||||||
|
//Interpolation Ranges are not used
|
||||||
|
u32 tempBoneTS;
|
||||||
|
numofs tempBoneNumOfs;
|
||||||
|
core::array<numofs> tempNumOfsList;
|
||||||
|
float tempBoneValue;
|
||||||
|
s16 tempBoneShort;
|
||||||
|
for(u32 i=0; i<M2MBones.size(); i++)
|
||||||
|
{
|
||||||
|
if(M2MBones[i].translation.header.TimeStamp.num>0)
|
||||||
|
{
|
||||||
|
tempNumOfsList.clear();
|
||||||
|
MeshFile->seek(M2MBones[i].translation.header.TimeStamp.ofs);
|
||||||
|
for(u32 j=0; j<M2MBones[i].translation.header.TimeStamp.num;j++)
|
||||||
|
{
|
||||||
|
MeshFile->read(&tempBoneNumOfs, sizeof(numofs));
|
||||||
|
tempNumOfsList.push_back(tempBoneNumOfs);
|
||||||
|
}
|
||||||
|
for(u32 j=0; j<tempNumOfsList.size();j++)
|
||||||
|
{
|
||||||
|
numofs n = tempNumOfsList[j];
|
||||||
|
if(n.num > 0 && M2MAnimations[j].flags & 0x20)
|
||||||
|
{
|
||||||
|
MeshFile->seek(n.ofs);
|
||||||
|
for(u32 k=0; k<n.num;k++)
|
||||||
|
{
|
||||||
|
MeshFile->read(&tempBoneTS, sizeof(u32));
|
||||||
|
M2MBones[i].translation.timestamps.push_back(tempBoneTS+M2MAnimations[j].start);//Bit of a HACK squash Multitimeline into single timeline.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(M2MBones[i].rotation.header.TimeStamp.num>0)
|
||||||
|
{
|
||||||
|
tempNumOfsList.clear();
|
||||||
|
MeshFile->seek(M2MBones[i].rotation.header.TimeStamp.ofs);
|
||||||
|
for(u32 j=0; j<M2MBones[i].rotation.header.TimeStamp.num;j++)
|
||||||
|
{
|
||||||
|
MeshFile->read(&tempBoneNumOfs, sizeof(numofs));
|
||||||
|
tempNumOfsList.push_back(tempBoneNumOfs);
|
||||||
|
}
|
||||||
|
for(u32 j=0; j<tempNumOfsList.size();j++)
|
||||||
|
{
|
||||||
|
numofs n = tempNumOfsList[j];
|
||||||
|
if(n.num > 0 && M2MAnimations[j].flags & 0x20)
|
||||||
|
{
|
||||||
|
MeshFile->seek(n.ofs);
|
||||||
|
for(u32 k=0; k<n.num;k++)
|
||||||
|
{
|
||||||
|
MeshFile->read(&tempBoneTS, sizeof(u32));
|
||||||
|
M2MBones[i].rotation.timestamps.push_back(tempBoneTS+M2MAnimations[j].start);//Bit of a HACK squash Multitimeline into single timeline.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(M2MBones[i].scaling.header.TimeStamp.num>0)
|
||||||
|
{
|
||||||
|
tempNumOfsList.clear();
|
||||||
|
MeshFile->seek(M2MBones[i].scaling.header.TimeStamp.ofs);
|
||||||
|
for(u32 j=0; j<M2MBones[i].scaling.header.TimeStamp.num;j++)
|
||||||
|
{
|
||||||
|
MeshFile->read(&tempBoneNumOfs, sizeof(numofs));
|
||||||
|
tempNumOfsList.push_back(tempBoneNumOfs);
|
||||||
|
}
|
||||||
|
for(u32 j=0; j<tempNumOfsList.size();j++)
|
||||||
|
{
|
||||||
|
numofs n = tempNumOfsList[j];
|
||||||
|
if(n.num > 0 && M2MAnimations[j].flags & 0x20)
|
||||||
|
{
|
||||||
|
MeshFile->seek(n.ofs);
|
||||||
|
for(u32 k=0; k<n.num;k++)
|
||||||
|
{
|
||||||
|
MeshFile->read(&tempBoneTS, sizeof(u32));
|
||||||
|
M2MBones[i].scaling.timestamps.push_back(tempBoneTS+M2MAnimations[j].start);//Bit of a HACK squash Multitimeline into single timeline.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(M2MBones[i].translation.header.Values.num>0)
|
||||||
|
{
|
||||||
|
tempNumOfsList.clear();
|
||||||
|
MeshFile->seek(M2MBones[i].translation.header.Values.ofs);
|
||||||
|
for(u32 j=0; j<M2MBones[i].translation.header.Values.num;j++)
|
||||||
|
{
|
||||||
|
MeshFile->read(&tempBoneNumOfs, sizeof(numofs));
|
||||||
|
tempNumOfsList.push_back(tempBoneNumOfs);
|
||||||
|
}
|
||||||
|
for(u32 j=0; j<tempNumOfsList.size();j++)
|
||||||
|
{
|
||||||
|
numofs n = tempNumOfsList[j];
|
||||||
|
if(n.num > 0 && M2MAnimations[j].flags & 0x20)
|
||||||
|
{
|
||||||
|
MeshFile->seek(n.ofs);
|
||||||
|
|
||||||
|
for(u32 k=0; k<n.num*3;k++)
|
||||||
|
{
|
||||||
|
MeshFile->read(&tempBoneValue, sizeof(float));
|
||||||
|
M2MBones[i].translation.values.push_back(tempBoneValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(M2MBones[i].rotation.header.Values.num>0)
|
||||||
|
{
|
||||||
|
tempNumOfsList.clear();
|
||||||
|
MeshFile->seek(M2MBones[i].rotation.header.Values.ofs);
|
||||||
|
for(u32 j=0; j<M2MBones[i].rotation.header.Values.num;j++)
|
||||||
|
{
|
||||||
|
MeshFile->read(&tempBoneNumOfs, sizeof(numofs));
|
||||||
|
tempNumOfsList.push_back(tempBoneNumOfs);
|
||||||
|
}
|
||||||
|
for(u32 j=0; j<tempNumOfsList.size();j++)
|
||||||
|
{
|
||||||
|
numofs n = tempNumOfsList[j];
|
||||||
|
if(n.num > 0 && M2MAnimations[j].flags & 0x20)
|
||||||
|
{
|
||||||
|
MeshFile->seek(n.ofs);
|
||||||
|
for(u32 k=0; k<n.num*4;k++)
|
||||||
|
{
|
||||||
|
MeshFile->read(&tempBoneShort, sizeof(s16));
|
||||||
|
tempBoneValue=(tempBoneShort>0?tempBoneShort-32767:tempBoneShort+32767)/32767.0f;
|
||||||
|
M2MBones[i].rotation.values.push_back(tempBoneValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(M2MBones[i].scaling.header.Values.num>0)
|
||||||
|
{
|
||||||
|
tempNumOfsList.clear();
|
||||||
|
MeshFile->seek(M2MBones[i].scaling.header.Values.ofs);
|
||||||
|
for(u32 j=0; j<M2MBones[i].scaling.header.Values.num;j++)
|
||||||
|
{
|
||||||
|
MeshFile->read(&tempBoneNumOfs, sizeof(numofs));
|
||||||
|
tempNumOfsList.push_back(tempBoneNumOfs);
|
||||||
|
}
|
||||||
|
for(u32 j=0; j<tempNumOfsList.size();j++)
|
||||||
|
{
|
||||||
|
numofs n = tempNumOfsList[j];
|
||||||
|
if(n.num > 0 && M2MAnimations[j].flags & 0x20)
|
||||||
|
{
|
||||||
|
MeshFile->seek(n.ofs);
|
||||||
|
for(u32 k=0; k<n.num*3;k++)
|
||||||
|
{
|
||||||
|
MeshFile->read(&tempBoneValue, sizeof(float));
|
||||||
|
M2MBones[i].scaling.values.push_back(tempBoneValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
DEBUG(logdebug("Read %u Bones",M2MBones.size()));
|
DEBUG(logdebug("Read %u Bones",M2MBones.size()));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CM2MeshFileLoader::ReadAnimationData()
|
||||||
|
{
|
||||||
|
logdebug("Reading Animation Data");
|
||||||
|
//Global Sequences. This is global data
|
||||||
|
u32 tempGlobalSeq;
|
||||||
|
if(!M2MGlobalSequences.empty())
|
||||||
|
{
|
||||||
|
M2MGlobalSequences.clear();
|
||||||
|
}
|
||||||
|
MeshFile->seek(header.GlobalSequences.ofs);
|
||||||
|
for(u32 i=0;i<header.GlobalSequences.num;i++)
|
||||||
|
{
|
||||||
|
MeshFile->read(&tempGlobalSeq,sizeof(u32));
|
||||||
|
M2MGlobalSequences.push_back(tempGlobalSeq);
|
||||||
|
DEBUG(logdebug("Global Sequence %u End %u",i,tempGlobalSeq));
|
||||||
|
}
|
||||||
|
DEBUG(logdebug("Read %u Global Sequence entries",M2MGlobalSequences.size()));
|
||||||
|
|
||||||
|
//BoneLookupTable. This is global data
|
||||||
|
u16 tempBoneLookup;
|
||||||
|
if(!M2MBoneLookupTable.empty())
|
||||||
|
{
|
||||||
|
M2MBoneLookupTable.clear();
|
||||||
|
}
|
||||||
|
MeshFile->seek(header.BoneLookupTable.ofs);
|
||||||
|
for(u32 i=0;i<header.BoneLookupTable.num;i++)
|
||||||
|
{
|
||||||
|
MeshFile->read(&tempBoneLookup,sizeof(u16));
|
||||||
|
M2MBoneLookupTable.push_back(tempBoneLookup);
|
||||||
|
DEBUG(logdebug("BoneLookupTable %u Value %u",i,tempBoneLookup));
|
||||||
|
}
|
||||||
|
DEBUG(logdebug("Read %u BoneLookupTable entries",M2MBoneLookupTable.size()));
|
||||||
|
|
||||||
|
//SkeleBoneLookupTable. This is global data
|
||||||
|
u16 tempSkeleBoneLookup;
|
||||||
|
if(!M2MSkeleBoneLookupTable.empty())
|
||||||
|
{
|
||||||
|
M2MSkeleBoneLookupTable.clear();
|
||||||
|
}
|
||||||
|
MeshFile->seek(header.SkelBoneLookup.ofs);
|
||||||
|
for(u32 i=0;i<header.SkelBoneLookup.num;i++)
|
||||||
|
{
|
||||||
|
MeshFile->read(&tempSkeleBoneLookup,sizeof(u16));
|
||||||
|
M2MSkeleBoneLookupTable.push_back(tempSkeleBoneLookup);
|
||||||
|
DEBUG(logdebug("SkeleBoneLookupTable %u Value %u",i,tempSkeleBoneLookup));
|
||||||
|
}
|
||||||
|
DEBUG(logdebug("Read %u SkeleBoneLookupTable entries",M2MSkeleBoneLookupTable.size()));
|
||||||
|
|
||||||
|
//Animations. This is global data
|
||||||
|
u32 laststart = 0;
|
||||||
|
if(!M2MAnimations.empty())
|
||||||
|
{
|
||||||
|
M2MAnimations.clear();
|
||||||
|
}
|
||||||
|
MeshFile->seek(header.Animations.ofs);
|
||||||
|
for(u32 i=0;i<header.Animations.num;i++)
|
||||||
|
{
|
||||||
|
Animation tempAnimation;
|
||||||
|
if(header.version < 0x108)
|
||||||
|
{
|
||||||
|
RawAnimation tempRaw;
|
||||||
|
MeshFile->read(&tempRaw,sizeof(RawAnimation));
|
||||||
|
tempAnimation.animationID = tempRaw.animationID;
|
||||||
|
tempAnimation.flags = tempRaw.flags;
|
||||||
|
tempAnimation.start = tempRaw.start;
|
||||||
|
tempAnimation.end = tempRaw.end;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RawAnimationWOTLK tempRaw;
|
||||||
|
MeshFile->read(&tempRaw,sizeof(RawAnimationWOTLK));
|
||||||
|
tempAnimation.animationID = tempRaw.animationID;
|
||||||
|
tempAnimation.subanimationID = tempRaw.subanimationID;
|
||||||
|
tempAnimation.flags = tempRaw.flags;
|
||||||
|
tempAnimation.start = laststart;
|
||||||
|
tempAnimation.end = laststart + tempRaw.length;
|
||||||
|
laststart += tempRaw.length + 1000;
|
||||||
|
}
|
||||||
|
M2MAnimations.push_back(tempAnimation);
|
||||||
|
DEBUG(logdebug("Animation %u Id %u Start %u End %u",i,tempAnimation.animationID,tempAnimation.start,tempAnimation.end));
|
||||||
|
}
|
||||||
|
DEBUG(logdebug("Read %u Animations",M2MAnimations.size()));
|
||||||
|
//Animation Lookup. This is global data
|
||||||
|
s16 tempAniLookup;
|
||||||
|
if(!M2MAnimationLookup.empty())
|
||||||
|
{
|
||||||
|
M2MAnimationLookup.clear();
|
||||||
|
}
|
||||||
|
MeshFile->seek(header.AnimationLookup.ofs);
|
||||||
|
for(u32 i=0;i<header.AnimationLookup.num;i++)
|
||||||
|
{
|
||||||
|
MeshFile->read(&tempAniLookup,sizeof(s16));
|
||||||
|
M2MAnimationLookup.push_back(tempAniLookup);
|
||||||
|
DEBUG(logdebug("Animation Lookup %u Id %u",i,tempAniLookup));
|
||||||
|
}
|
||||||
|
DEBUG(logdebug("Read %u AnimationLookup",M2MAnimationLookup.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CM2MeshFileLoader::ReadTextureDefinitions()
|
void CM2MeshFileLoader::ReadTextureDefinitions()
|
||||||
@ -305,8 +531,8 @@ void CM2MeshFileLoader::ReadTextureDefinitions()
|
|||||||
{
|
{
|
||||||
M2MTextureLookup.clear();
|
M2MTextureLookup.clear();
|
||||||
}
|
}
|
||||||
MeshFile->seek(header.ofsTexLookup);
|
MeshFile->seek(header.TexLookup.ofs);
|
||||||
for(u32 i=0;i<header.nTexLookup;i++)
|
for(u32 i=0;i<header.TexLookup.num;i++)
|
||||||
{
|
{
|
||||||
MeshFile->read(&tempM2TexLookup,sizeof(u16));
|
MeshFile->read(&tempM2TexLookup,sizeof(u16));
|
||||||
M2MTextureLookup.push_back(tempM2TexLookup);
|
M2MTextureLookup.push_back(tempM2TexLookup);
|
||||||
@ -320,8 +546,8 @@ void CM2MeshFileLoader::ReadTextureDefinitions()
|
|||||||
{
|
{
|
||||||
M2MTextureDef.clear();
|
M2MTextureDef.clear();
|
||||||
}
|
}
|
||||||
MeshFile->seek(header.ofsTextures);
|
MeshFile->seek(header.Textures.ofs);
|
||||||
for(u32 i=0;i<header.nTextures;i++)
|
for(u32 i=0;i<header.Textures.num;i++)
|
||||||
{
|
{
|
||||||
MeshFile->read(&tempM2TexDef,sizeof(TextureDefinition));
|
MeshFile->read(&tempM2TexDef,sizeof(TextureDefinition));
|
||||||
M2MTextureDef.push_back(tempM2TexDef);
|
M2MTextureDef.push_back(tempM2TexDef);
|
||||||
@ -335,8 +561,8 @@ void CM2MeshFileLoader::ReadTextureDefinitions()
|
|||||||
{
|
{
|
||||||
M2MRenderFlags.clear();
|
M2MRenderFlags.clear();
|
||||||
}
|
}
|
||||||
MeshFile->seek(header.ofsTexFlags);
|
MeshFile->seek(header.TexFlags.ofs);
|
||||||
for(u32 i=0;i<header.nTexFlags;i++)
|
for(u32 i=0;i<header.TexFlags.num;i++)
|
||||||
{
|
{
|
||||||
MeshFile->read(&tempM2RF,sizeof(RenderFlags));
|
MeshFile->read(&tempM2RF,sizeof(RenderFlags));
|
||||||
M2MRenderFlags.push_back(tempM2RF);
|
M2MRenderFlags.push_back(tempM2RF);
|
||||||
@ -364,7 +590,7 @@ void CM2MeshFileLoader::ReadTextureDefinitions()
|
|||||||
bool CM2MeshFileLoader::load()
|
bool CM2MeshFileLoader::load()
|
||||||
{
|
{
|
||||||
DEBUG(logdebug("Trying to open file %s",MeshFile->getFileName()));
|
DEBUG(logdebug("Trying to open file %s",MeshFile->getFileName()));
|
||||||
|
logdebug("Trying to open file %s",MeshFile->getFileName());
|
||||||
|
|
||||||
MeshFile->read(&header,20);
|
MeshFile->read(&header,20);
|
||||||
DEBUG(logdebug("M2 Version %X",header.version));
|
DEBUG(logdebug("M2 Version %X",header.version));
|
||||||
@ -372,23 +598,50 @@ DEBUG(logdebug("M2 Version %X",header.version));
|
|||||||
switch(header.version)
|
switch(header.version)
|
||||||
{
|
{
|
||||||
case 0x100:
|
case 0x100:
|
||||||
case 0x104://HACK
|
case 0x104://NEED CHECK
|
||||||
case 0x105://HACK
|
case 0x105://NEED CHECK
|
||||||
case 0x106://HACK
|
case 0x106://NEED CHECK
|
||||||
case 0x107://HACK
|
case 0x107://NEED CHECK
|
||||||
{
|
{
|
||||||
MeshFile->read((u8*)&header+20,sizeof(ModelHeader)-20);
|
MeshFile->read((u8*)&header+20,sizeof(ModelHeader)-20);
|
||||||
ReadVertices();
|
MeshFile->seek(header.Views.ofs);
|
||||||
MeshFile->seek(header.ofsViews);
|
|
||||||
MeshFile->read(¤tView,sizeof(ModelView));
|
MeshFile->read(¤tView,sizeof(ModelView));
|
||||||
ReadViewData(MeshFile);
|
ReadViewData(MeshFile);
|
||||||
|
ReadVertices();
|
||||||
|
|
||||||
ReadTextureDefinitions();
|
ReadTextureDefinitions();
|
||||||
ReadAnimationData();
|
ReadAnimationData();
|
||||||
|
|
||||||
|
ReadBones();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x108:
|
case 0x108:
|
||||||
{
|
{
|
||||||
|
//This is pretty ugly... Any suggestions how to make this nicer?
|
||||||
|
MeshFile->read((u8*)&header+0x14,24);//nGlobalSequences - ofsAnimationLookup
|
||||||
|
MeshFile->read((u8*)&header+0x34,28);//nBones - nViews
|
||||||
|
MeshFile->read((u8*)&header+0x54,24);//nColors - nTransparency
|
||||||
|
MeshFile->read((u8*)&header+0x74,sizeof(ModelHeader)-0x74);//nTexAnims - END
|
||||||
|
|
||||||
|
std::string SkinName = MeshFile->getFileName();
|
||||||
|
SkinName = SkinName.substr(0, SkinName.length()-3) + "00.skin"; // FIX ME if we need more skins
|
||||||
|
io::IReadFile* SkinFile = io::IrrCreateIReadFileBasic(Device, SkinName.c_str());
|
||||||
|
if (!SkinFile)
|
||||||
|
{
|
||||||
|
logerror("Error! Skin file not found: %s", SkinName.c_str());
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
SkinFile->seek(4); // Header of Skin Files is always SKIN
|
||||||
|
SkinFile->read(¤tView,sizeof(ModelView));
|
||||||
|
ReadViewData(SkinFile);
|
||||||
|
SkinFile->drop();
|
||||||
|
|
||||||
|
ReadVertices();
|
||||||
|
|
||||||
|
ReadTextureDefinitions();
|
||||||
|
ReadAnimationData();
|
||||||
|
|
||||||
|
ReadBonesWOTLK();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -420,18 +673,18 @@ for(u32 i=0;i<M2MBones.size();i++)
|
|||||||
}
|
}
|
||||||
Joint=AnimatedMesh->createJoint(ParentJoint);
|
Joint=AnimatedMesh->createJoint(ParentJoint);
|
||||||
|
|
||||||
if(M2MBones[i].translation.header.nValues>0)
|
if(M2MBones[i].translation.timestamps.size()>0)
|
||||||
{
|
{
|
||||||
for(u32 j=0;j<M2MBones[i].translation.header.nValues;j++)
|
for(u32 j=0;j<M2MBones[i].translation.timestamps.size();j++)
|
||||||
{
|
{
|
||||||
scene::CM2Mesh::SPositionKey* pos=AnimatedMesh->createPositionKey(Joint);
|
scene::CM2Mesh::SPositionKey* pos=AnimatedMesh->createPositionKey(Joint);
|
||||||
pos->frame=M2MBones[i].translation.timestamps[j];
|
pos->frame=M2MBones[i].translation.timestamps[j];
|
||||||
pos->position=fixCoordSystem(core::vector3df(M2MBones[i].translation.values[j*3],M2MBones[i].translation.values[j*3+1],M2MBones[i].translation.values[j*3+2]));
|
pos->position=fixCoordSystem(core::vector3df(M2MBones[i].translation.values[j*3],M2MBones[i].translation.values[j*3+1],M2MBones[i].translation.values[j*3+2]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(M2MBones[i].rotation.header.nValues>0)
|
if(M2MBones[i].rotation.timestamps.size()>0)
|
||||||
{
|
{
|
||||||
for(u32 j=0;j<M2MBones[i].rotation.header.nValues;j++)
|
for(u32 j=0;j<M2MBones[i].rotation.timestamps.size();j++)
|
||||||
{
|
{
|
||||||
scene::CM2Mesh::SRotationKey* rot=AnimatedMesh->createRotationKey(Joint);
|
scene::CM2Mesh::SRotationKey* rot=AnimatedMesh->createRotationKey(Joint);
|
||||||
rot->frame=M2MBones[i].rotation.timestamps[j];
|
rot->frame=M2MBones[i].rotation.timestamps[j];
|
||||||
@ -442,9 +695,9 @@ for(u32 i=0;i<M2MBones.size();i++)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(M2MBones[i].scaling.header.nValues>0)
|
if(M2MBones[i].scaling.timestamps.size()>0)
|
||||||
{
|
{
|
||||||
for(u32 j=0;j<M2MBones[i].scaling.header.nValues;j++)
|
for(u32 j=0;j<M2MBones[i].scaling.timestamps.size();j++)
|
||||||
{
|
{
|
||||||
scene::CM2Mesh::SScaleKey* scale=AnimatedMesh->createScaleKey(Joint);
|
scene::CM2Mesh::SScaleKey* scale=AnimatedMesh->createScaleKey(Joint);
|
||||||
scale->frame=M2MBones[i].scaling.timestamps[j];
|
scale->frame=M2MBones[i].scaling.timestamps[j];
|
||||||
@ -481,7 +734,7 @@ for(u32 i=0;i<M2MVertices.size();i++)
|
|||||||
M2Vertices.push_back(video::S3DVertex(core::vector3df(M2MVertices[i].pos.X,M2MVertices[i].pos.Y,M2MVertices[i].pos.Z),core::vector3df(M2MVertices[i].normal.X,M2MVertices[i].normal.Y,M2MVertices[i].normal.Z), video::SColor(255,100,100,100),M2MVertices[i].texcoords));
|
M2Vertices.push_back(video::S3DVertex(core::vector3df(M2MVertices[i].pos.X,M2MVertices[i].pos.Y,M2MVertices[i].pos.Z),core::vector3df(M2MVertices[i].normal.X,M2MVertices[i].normal.Y,M2MVertices[i].normal.Z), video::SColor(255,100,100,100),M2MVertices[i].texcoords));
|
||||||
}
|
}
|
||||||
//Loop through the submeshes
|
//Loop through the submeshes
|
||||||
for(u32 i=0; i < currentView.nSub;i++)//
|
for(u32 i=0; i < currentView.Submesh.num;i++)//
|
||||||
{
|
{
|
||||||
//Now, M2MTriangles refers to M2MIndices and not to M2MVertices.
|
//Now, M2MTriangles refers to M2MIndices and not to M2MVertices.
|
||||||
scene::SSkinMeshBuffer *MeshBuffer = AnimatedMesh->createBuffer();
|
scene::SSkinMeshBuffer *MeshBuffer = AnimatedMesh->createBuffer();
|
||||||
@ -551,7 +804,7 @@ for(u32 i=0; i < currentView.nSub;i++)//
|
|||||||
}
|
}
|
||||||
|
|
||||||
MeshBuffer->recalculateBoundingBox();
|
MeshBuffer->recalculateBoundingBox();
|
||||||
if(header.nAnimations==0 && header.nGlobalSequences == 0)
|
if(header.Animations.num==0 && header.GlobalSequences.num == 0)
|
||||||
MeshBuffer->setHardwareMappingHint(EHM_STATIC);
|
MeshBuffer->setHardwareMappingHint(EHM_STATIC);
|
||||||
else
|
else
|
||||||
MeshBuffer->setHardwareMappingHint(EHM_STREAM);
|
MeshBuffer->setHardwareMappingHint(EHM_STREAM);
|
||||||
@ -559,7 +812,6 @@ for(u32 i=0; i < currentView.nSub;i++)//
|
|||||||
}
|
}
|
||||||
Device->getSceneManager()->getMeshManipulator()->flipSurfaces(AnimatedMesh);
|
Device->getSceneManager()->getMeshManipulator()->flipSurfaces(AnimatedMesh);
|
||||||
|
|
||||||
// SkinFile->drop();
|
|
||||||
M2MTriangles.clear();
|
M2MTriangles.clear();
|
||||||
M2Vertices.clear();
|
M2Vertices.clear();
|
||||||
M2Indices.clear();
|
M2Indices.clear();
|
||||||
|
|||||||
@ -10,87 +10,56 @@ namespace irr
|
|||||||
namespace scene
|
namespace scene
|
||||||
{
|
{
|
||||||
|
|
||||||
|
struct numofs {
|
||||||
|
u32 num;
|
||||||
|
u32 ofs;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct ModelHeader {
|
struct ModelHeader {
|
||||||
c8 id[4]; //0x00
|
c8 id[4]; //0x00
|
||||||
u32 version;
|
u32 version;
|
||||||
u32 nameLength;
|
numofs name;
|
||||||
u32 nameOfs;
|
|
||||||
u32 type; //0x10
|
u32 type; //0x10
|
||||||
|
|
||||||
//Anim Block @ 0x14
|
//Anim Block @ 0x14
|
||||||
u32 nGlobalSequences;
|
numofs GlobalSequences;
|
||||||
u32 ofsGlobalSequences;
|
numofs Animations;
|
||||||
u32 nAnimations;
|
numofs AnimationLookup;
|
||||||
u32 ofsAnimations; //0x20
|
numofs D; //Absent in WOTLK
|
||||||
u32 nAnimationLookup;
|
numofs Bones;
|
||||||
u32 ofsAnimationLookup;
|
numofs SkelBoneLookup;
|
||||||
u32 nD;
|
numofs Vertices;
|
||||||
u32 ofsD; //0x30
|
numofs Views; //ofs Absent in WOTLK
|
||||||
u32 nBones;
|
numofs Colors;
|
||||||
u32 ofsBones;
|
numofs Textures;
|
||||||
u32 nSkelBoneLookup;
|
numofs Transparency;
|
||||||
u32 ofsSkelBoneLookup; //0x40
|
numofs I; //Absent in WoTLK
|
||||||
|
numofs TexAnims;
|
||||||
u32 nVertices; //0x44
|
numofs TexReplace;
|
||||||
u32 ofsVertices;
|
numofs TexFlags;
|
||||||
u32 nViews; // number of skins ?
|
numofs BoneLookupTable;
|
||||||
u32 ofsViews; //0x50
|
numofs TexLookup;
|
||||||
|
numofs TexUnitLookup;
|
||||||
u32 nColors;
|
numofs TransparencyLookup;
|
||||||
u32 ofsColors;
|
numofs TexAnimLookup;
|
||||||
|
|
||||||
u32 nTextures;
|
|
||||||
u32 ofsTextures; //0x60
|
|
||||||
|
|
||||||
u32 nTransparency;
|
|
||||||
u32 ofsTransparency;
|
|
||||||
u32 nI;
|
|
||||||
u32 ofsI; //0x70
|
|
||||||
u32 nTexAnims;
|
|
||||||
u32 ofsTexAnims;
|
|
||||||
u32 nTexReplace;
|
|
||||||
u32 ofsTexReplace; //0x80
|
|
||||||
|
|
||||||
u32 nTexFlags;
|
|
||||||
u32 ofsTexFlags;
|
|
||||||
u32 nBoneLookupTable;
|
|
||||||
u32 ofsBoneLookupTable; //0x90
|
|
||||||
|
|
||||||
u32 nTexLookup;
|
|
||||||
u32 ofsTexLookup;
|
|
||||||
|
|
||||||
u32 nTexUnitLookup;
|
|
||||||
u32 ofsTexUnitLookup; //0xa0
|
|
||||||
u32 nTransparencyLookup;
|
|
||||||
u32 ofsTransparencyLookup;
|
|
||||||
u32 nTexAnimLookup;
|
|
||||||
u32 ofsTexAnimLookup; //0xb0
|
|
||||||
|
|
||||||
f32 floats[14];
|
f32 floats[14];
|
||||||
|
|
||||||
u32 nBoundingTriangles;
|
numofs BoundingTriangles;
|
||||||
u32 ofsBoundingTriangles; //0xf0
|
numofs BoundingVertices;
|
||||||
u32 nBoundingVertices;
|
numofs BoundingNormals;
|
||||||
u32 ofsBoundingVertices;
|
|
||||||
u32 nBoundingNormals;
|
|
||||||
u32 ofsBoundingNormals; //0x100
|
|
||||||
|
|
||||||
u32 nAttachments;
|
numofs Attachments;
|
||||||
u32 ofsAttachments;
|
numofs AttachLookup;
|
||||||
u32 nAttachLookup;
|
numofs Events;
|
||||||
u32 ofsAttachLookup; //0x110
|
numofs Lights;
|
||||||
u32 nAttachments_2;
|
numofs Cameras;
|
||||||
u32 ofsAttachments_2;
|
numofs CameraLookup;
|
||||||
u32 nLights;
|
numofs RibbonEmitters;
|
||||||
u32 ofsLights; //0x120
|
numofs ParticleEmitters;
|
||||||
u32 nCameras;
|
|
||||||
u32 ofsCameras;
|
//WOTLK has one more field which is only set under specific conditions.
|
||||||
u32 nCameraLookup;
|
|
||||||
u32 ofsnCameraLookup; //0x130
|
|
||||||
u32 nRibbonEmitters;
|
|
||||||
u32 ofsRibbonEmitters;
|
|
||||||
u32 nParticleEmitters;
|
|
||||||
u32 ofsParticleEmitters;//0x140
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -112,16 +81,15 @@ struct ModelVertex {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ModelView {
|
struct ModelView {
|
||||||
// c8 id[4]; // always "SKIN"
|
numofs Index; // Vertices in this model (index into vertices[])
|
||||||
u32 nIndex, ofsIndex; // Vertices in this model (index into vertices[])
|
numofs Triangle; // indices
|
||||||
u32 nTris, ofsTris; // indices
|
numofs Properties; // additional vtx properties (mostly 0?)
|
||||||
u32 nProps, ofsProps; // additional vtx properties
|
numofs Submesh; // submeshes
|
||||||
u32 nSub, ofsSub; // materials/renderops/submeshes
|
numofs Tex; // material properties/textures
|
||||||
u32 nTex, ofsTex; // material properties/textures
|
u32 lod; // LOD bias? unknown
|
||||||
u32 lod; // LOD bias?
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ModelViewSubmesh {
|
struct ModelViewSubmesh { //Curse you BLIZZ for not using numofs here
|
||||||
u32 meshpartId;
|
u32 meshpartId;
|
||||||
u16 ofsVertex;//Starting vertex number for this submesh
|
u16 ofsVertex;//Starting vertex number for this submesh
|
||||||
u16 nVertex;
|
u16 nVertex;
|
||||||
@ -151,7 +119,7 @@ struct RenderFlags{
|
|||||||
u16 blending;
|
u16 blending;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Animation{
|
struct RawAnimation{
|
||||||
u32 animationID;
|
u32 animationID;
|
||||||
u32 start, end;
|
u32 start, end;
|
||||||
float movespeed;
|
float movespeed;
|
||||||
@ -163,34 +131,52 @@ struct Animation{
|
|||||||
u16 unk3;
|
u16 unk3;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct RawAnimationWOTLK{
|
||||||
|
u16 animationID, subanimationID;
|
||||||
|
u32 length;
|
||||||
|
float movespeed;
|
||||||
|
u32 flags;
|
||||||
|
u16 probability, unused;
|
||||||
|
u32 unk1, unk2, playbackspeed;
|
||||||
|
float bbox[6];
|
||||||
|
float radius;
|
||||||
|
s16 indexSameID;
|
||||||
|
u16 index;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Animation{
|
||||||
|
u32 animationID;
|
||||||
|
u32 subanimationID;
|
||||||
|
u32 start, end;
|
||||||
|
u32 flags;
|
||||||
|
};
|
||||||
|
|
||||||
struct AnimBlockHead{
|
struct AnimBlockHead{
|
||||||
s16 interpolationType;
|
s16 interpolationType;
|
||||||
s16 globalSequenceID;
|
s16 globalSequenceID;
|
||||||
u32 nInterpolationRange;
|
numofs InterpolationRanges; //Missing in WotLK
|
||||||
u32 ofsInterpolationRange;
|
numofs TimeStamp;
|
||||||
u32 nTimeStamp;
|
numofs Values;
|
||||||
u32 ofsTimeStamp;
|
|
||||||
u32 nValues;
|
|
||||||
u32 ofsValues;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InterpolationRange{
|
// struct InterpolationRange{
|
||||||
u32 start, end;
|
// u32 start, end;
|
||||||
};
|
// };
|
||||||
|
|
||||||
struct AnimBlock{
|
struct AnimBlock{
|
||||||
AnimBlockHead header;
|
AnimBlockHead header;
|
||||||
core::array<InterpolationRange> keyframes;
|
// core::array<InterpolationRange> keyframes; // We are not using this
|
||||||
core::array<u32> timestamps;
|
core::array<u32> timestamps;
|
||||||
core::array<float> values;
|
core::array<float> values;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Bone{
|
struct Bone{
|
||||||
s32 indexF;
|
s32 SkelBoneIndex;
|
||||||
u32 flags;
|
u32 flags;
|
||||||
s16 parentBone;
|
s16 parentBone;
|
||||||
u16 unk1;
|
u16 unk1;
|
||||||
u32 unk2;
|
u16 unk2;
|
||||||
|
u16 unk3;
|
||||||
AnimBlock translation, rotation, scaling;
|
AnimBlock translation, rotation, scaling;
|
||||||
core::vector3df PivotPoint;
|
core::vector3df PivotPoint;
|
||||||
};
|
};
|
||||||
@ -218,6 +204,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
bool load();
|
bool load();
|
||||||
|
void ReadBones();
|
||||||
|
void ReadBonesWOTLK();
|
||||||
void ReadVertices();
|
void ReadVertices();
|
||||||
void ReadTextureDefinitions();
|
void ReadTextureDefinitions();
|
||||||
void ReadAnimationData();
|
void ReadAnimationData();
|
||||||
@ -249,6 +237,7 @@ private:
|
|||||||
core::array<RenderFlags> M2MRenderFlags;
|
core::array<RenderFlags> M2MRenderFlags;
|
||||||
core::array<u32> M2MGlobalSequences;
|
core::array<u32> M2MGlobalSequences;
|
||||||
core::array<Animation> M2MAnimations;
|
core::array<Animation> M2MAnimations;
|
||||||
|
core::array<s16> M2MAnimationLookup;
|
||||||
core::array<Bone> M2MBones;
|
core::array<Bone> M2MBones;
|
||||||
core::array<u16> M2MBoneLookupTable;
|
core::array<u16> M2MBoneLookupTable;
|
||||||
core::array<u16> M2MSkeleBoneLookupTable;
|
core::array<u16> M2MSkeleBoneLookupTable;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user