* Rewritten M2 Animation loading code. Much nicer now.
Also: Lumirions updates for renderflags vertexcolor and materials to m2 loader and disabled model lighting in viewer since its set in the loader now (cherry picked from commit a5d909a8a5cf003615500169095700c2f525050b)
This commit is contained in:
parent
b77202fd1c
commit
57e8d3e844
@ -1,4 +1,4 @@
|
||||
// #define _DEBUG 1
|
||||
#define _DEBUG 1
|
||||
#include <iostream>
|
||||
#include "MemoryDataHolder.h"
|
||||
#include "MemoryInterface.h"
|
||||
@ -59,6 +59,7 @@ IAnimatedMesh* CM2MeshFileLoader::createMesh(io::IReadFile* file)
|
||||
|
||||
return AnimatedMesh;
|
||||
}
|
||||
|
||||
void CM2MeshFileLoader::ReadVertices()
|
||||
{
|
||||
//Vertices. Global data
|
||||
@ -137,264 +138,177 @@ void CM2MeshFileLoader::ReadViewData(io::IReadFile* file)
|
||||
|
||||
}
|
||||
|
||||
void CM2MeshFileLoader::ReadABlock(AnimBlock &ABlock, u8 datatype, u8 datanum)
|
||||
{
|
||||
// datatypes: 0 = float, 1 = short
|
||||
// datatype & datanum: datatype 0, datanum 3 --> read 3 floats
|
||||
MeshFile->read(&ABlock.header,4);
|
||||
if(header.version < 0x108)//Read/Skip Interpolation Ranges for preWOTLK
|
||||
MeshFile->read(&ABlock.header.InterpolationRanges,sizeof(numofs));
|
||||
MeshFile->read(&ABlock.header.TimeStamp,sizeof(numofs));
|
||||
MeshFile->read(&ABlock.header.Values,sizeof(numofs));
|
||||
u32 offset_next_entry = MeshFile->getPos();
|
||||
// logdebug("%u %u %u %u",datatype, datanum, ABlock.header.TimeStamp.num,ABlock.header.Values.num);
|
||||
|
||||
core::array<numofs> data_offsets;
|
||||
numofs tempNumOfs;
|
||||
io::IReadFile* AnimFile;
|
||||
|
||||
//Read Timestamps
|
||||
if(header.version < 0x108)
|
||||
data_offsets.push_back(ABlock.header.TimeStamp);
|
||||
else
|
||||
{
|
||||
MeshFile->seek(ABlock.header.TimeStamp.ofs);
|
||||
for(u32 i =0;i < ABlock.header.TimeStamp.num; i++)
|
||||
{
|
||||
MeshFile->read(&tempNumOfs,sizeof(numofs));
|
||||
data_offsets.push_back(tempNumOfs);
|
||||
}
|
||||
}
|
||||
for(u32 i = 0; i < data_offsets.size(); i++)
|
||||
{
|
||||
tempNumOfs = data_offsets[i];
|
||||
|
||||
if((M2MAnimations[i].flags & 0x20) == 0 && (M2MAnimations[i].flags & 0x40))
|
||||
continue;
|
||||
|
||||
u32 offset = 0;
|
||||
if(header.version >= 0x108)
|
||||
offset = M2MAnimations[i].start;//HACK: Squashing WoTLK multitimelines into one single timeline
|
||||
|
||||
if(header.version >= 0x108 && M2MAnimfiles[i] != 0)
|
||||
AnimFile = M2MAnimfiles[i];
|
||||
else
|
||||
AnimFile = MeshFile;
|
||||
AnimFile->seek(tempNumOfs.ofs);
|
||||
u32 tempTS;
|
||||
for(u32 j = 0; j < tempNumOfs.num; j++)
|
||||
{
|
||||
AnimFile->read(&tempTS,sizeof(u32));
|
||||
ABlock.timestamps.push_back(tempTS+offset);
|
||||
}
|
||||
}
|
||||
|
||||
data_offsets.clear();
|
||||
//Read Values
|
||||
if(header.version < 0x108)
|
||||
data_offsets.push_back(ABlock.header.Values);
|
||||
else
|
||||
{
|
||||
MeshFile->seek(ABlock.header.Values.ofs);
|
||||
for(u32 i =0;i < ABlock.header.Values.num; i++)
|
||||
{
|
||||
MeshFile->read(&tempNumOfs,sizeof(numofs));
|
||||
data_offsets.push_back(tempNumOfs);
|
||||
}
|
||||
}
|
||||
for(u32 i = 0; i < data_offsets.size(); i++)
|
||||
{
|
||||
tempNumOfs = data_offsets[i];
|
||||
if((M2MAnimations[i].flags & 0x20) == 0 && (M2MAnimations[i].flags & 0x40))
|
||||
continue;
|
||||
if(header.version >= 0x108 && M2MAnimfiles[i] != 0)
|
||||
AnimFile = M2MAnimfiles[i];
|
||||
else
|
||||
AnimFile = MeshFile;
|
||||
AnimFile->seek(tempNumOfs.ofs);
|
||||
s16 tempShort;
|
||||
s32 tempInt;
|
||||
f32 tempFloat;
|
||||
for(u32 j = 0; j < tempNumOfs.num * datanum; j++)
|
||||
{
|
||||
switch(datatype)
|
||||
{
|
||||
case ABDT_FLOAT:
|
||||
AnimFile->read(&tempFloat,sizeof(f32));
|
||||
break;
|
||||
case ABDT_SHORT:
|
||||
MeshFile->read(&tempShort, sizeof(s16));
|
||||
tempFloat=(tempShort>0?tempShort-32767:tempShort+32767)/32767.0f;
|
||||
break;
|
||||
case ABDT_INT:
|
||||
AnimFile->read(&tempInt,sizeof(s32));
|
||||
tempFloat=tempInt * 1.0f;
|
||||
break;
|
||||
}
|
||||
ABlock.values.push_back(tempFloat);
|
||||
}
|
||||
}
|
||||
|
||||
MeshFile->seek(offset_next_entry);
|
||||
}
|
||||
|
||||
|
||||
void CM2MeshFileLoader::ReadBones()
|
||||
{
|
||||
|
||||
//Bones. This is global data
|
||||
Bone tempBone;
|
||||
if(!M2MBones.empty())
|
||||
{
|
||||
//Bones. This is global data
|
||||
if(!M2MBones.empty())
|
||||
{
|
||||
M2MBones.clear();
|
||||
}
|
||||
MeshFile->seek(header.Bones.ofs);
|
||||
for(u32 i=0;i<header.Bones.num;i++)
|
||||
{
|
||||
}
|
||||
MeshFile->seek(header.Bones.ofs);
|
||||
for(u32 i=0;i<header.Bones.num;i++)
|
||||
{
|
||||
Bone tempBone;
|
||||
MeshFile->read(&tempBone,12+(header.version==0x100?0:4));
|
||||
|
||||
MeshFile->read(&tempBone.translation.header,sizeof(AnimBlockHead));
|
||||
MeshFile->read(&tempBone.rotation.header,sizeof(AnimBlockHead));
|
||||
MeshFile->read(&tempBone.scaling.header,sizeof(AnimBlockHead));
|
||||
ReadABlock(tempBone.translation,ABDT_FLOAT,3);
|
||||
ReadABlock(tempBone.rotation,(header.version>=0x104?ABDT_SHORT:ABDT_FLOAT),4);
|
||||
ReadABlock(tempBone.scaling,ABDT_FLOAT,3);
|
||||
|
||||
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));
|
||||
}
|
||||
DEBUG(logdebug("Read %u Bones",M2MBones.size()));
|
||||
|
||||
}
|
||||
//Fill in values referenced in Bones. local to each bone
|
||||
//Interpolation Ranges are not used
|
||||
u32 tempBoneTS;
|
||||
numofs tempBoneNumOfs;
|
||||
float tempBoneValue;
|
||||
for(u32 i=0; i<M2MBones.size(); i++)
|
||||
|
||||
|
||||
void CM2MeshFileLoader::ReadColors()
|
||||
{
|
||||
|
||||
if(M2MBones[i].translation.header.TimeStamp.num>0)
|
||||
if (!M2MVertexColor.empty())
|
||||
{
|
||||
MeshFile->seek(M2MBones[i].translation.header.TimeStamp.ofs);
|
||||
for(u32 j=0; j<M2MBones[i].translation.header.TimeStamp.num;j++)
|
||||
{
|
||||
MeshFile->read(&tempBoneTS, sizeof(u32));
|
||||
M2MBones[i].translation.timestamps.push_back(tempBoneTS);
|
||||
M2MVertexColor.clear();
|
||||
}
|
||||
}
|
||||
if(M2MBones[i].rotation.header.TimeStamp.num>0)
|
||||
//read vertex color and alpha offsets
|
||||
logdebug("Colors");
|
||||
MeshFile->seek(header.Colors.ofs);
|
||||
for(u32 i=0;i<header.Colors.num;i++)
|
||||
{
|
||||
MeshFile->seek(M2MBones[i].rotation.header.TimeStamp.ofs);
|
||||
for(u32 j=0; j<M2MBones[i].rotation.header.TimeStamp.num;j++)
|
||||
{
|
||||
MeshFile->read(&tempBoneTS, sizeof(u32));
|
||||
M2MBones[i].rotation.timestamps.push_back(tempBoneTS);
|
||||
}
|
||||
}
|
||||
if(M2MBones[i].scaling.header.TimeStamp.num>0)
|
||||
{
|
||||
MeshFile->seek(M2MBones[i].scaling.header.TimeStamp.ofs);
|
||||
for(u32 j=0; j<M2MBones[i].scaling.header.TimeStamp.num;j++)
|
||||
{
|
||||
MeshFile->read(&tempBoneTS, sizeof(u32));
|
||||
M2MBones[i].scaling.timestamps.push_back(tempBoneTS);
|
||||
}
|
||||
}
|
||||
if(M2MBones[i].translation.header.Values.num>0)
|
||||
{
|
||||
MeshFile->seek(M2MBones[i].translation.header.Values.ofs);
|
||||
for(u32 j=0; j<M2MBones[i].translation.header.Values.num*3;j++)
|
||||
{
|
||||
MeshFile->read(&tempBoneValue, sizeof(float));
|
||||
M2MBones[i].translation.values.push_back(tempBoneValue);
|
||||
}
|
||||
}
|
||||
if(M2MBones[i].rotation.header.Values.num>0)
|
||||
{
|
||||
MeshFile->seek(M2MBones[i].rotation.header.Values.ofs);
|
||||
for(u32 j=0; j<M2MBones[i].rotation.header.Values.num*4;j++)
|
||||
{
|
||||
if(header.version>=0x104)
|
||||
{
|
||||
s16 tempBoneShort;
|
||||
MeshFile->read(&tempBoneShort, sizeof(s16));
|
||||
tempBoneValue=(tempBoneShort>0?tempBoneShort-32767:tempBoneShort+32767)/32767.0f;
|
||||
M2MBones[i].rotation.values.push_back(tempBoneValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
MeshFile->read(&tempBoneValue, sizeof(f32));
|
||||
M2MBones[i].rotation.values.push_back(tempBoneValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(M2MBones[i].scaling.header.Values.num>0)
|
||||
{
|
||||
MeshFile->seek(M2MBones[i].scaling.header.Values.ofs);
|
||||
for(u32 j=0; j<M2MBones[i].scaling.header.Values.num*3;j++)
|
||||
{
|
||||
MeshFile->read(&tempBoneValue, sizeof(float));
|
||||
M2MBones[i].scaling.values.push_back(tempBoneValue);
|
||||
}
|
||||
VertexColor tempVC;
|
||||
logdebug("Color %u",i);
|
||||
ReadABlock(tempVC.Colors,ABDT_FLOAT,3);
|
||||
ReadABlock(tempVC.Alpha,ABDT_SHORT,1);
|
||||
M2MVertexColor.push_back(tempVC);
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG(logdebug("Read %u Bones",M2MBones.size()));
|
||||
}
|
||||
|
||||
void CM2MeshFileLoader::ReadBonesWOTLK()
|
||||
void CM2MeshFileLoader::ReadLights()
|
||||
{
|
||||
//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));
|
||||
if (!M2MLights.empty())
|
||||
{
|
||||
M2MLights.clear();
|
||||
}
|
||||
//read Lights
|
||||
MeshFile->seek(header.Lights.ofs);
|
||||
|
||||
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;
|
||||
//Animations can now be stored in anim files. To read quickly we need to swap the order of things.
|
||||
//We are not loading stuff by bone but by animation - every bone has data for all the animations (I hope...)
|
||||
//Animations MUST BE LOADED FIRST!!!!!
|
||||
bool use_animfile;
|
||||
io::IReadFile* AnimFile;
|
||||
for(u32 i=0; i<M2MAnimations.size(); i++)
|
||||
{
|
||||
use_animfile = (M2MAnimations[i].flags & 0x20) == 0;
|
||||
if(use_animfile)
|
||||
for(u32 i=0;i<header.Lights.num;i++)
|
||||
{
|
||||
std::string AnimName = MeshFile->getFileName().c_str();
|
||||
c8 ext[13];
|
||||
sprintf(ext,"%04d-%02d.anim",M2MAnimations[i].animationID,M2MAnimations[i].subanimationID);
|
||||
AnimName = AnimName.substr(0, AnimName.length()-3) + ext;
|
||||
AnimFile = io::IrrCreateIReadFileBasic(Device, AnimName.c_str());
|
||||
if (!AnimFile)
|
||||
{
|
||||
logerror("Error! Anim file not found: %s", AnimName.c_str());
|
||||
if(M2MAnimations[i].flags & 0x40)
|
||||
{
|
||||
logerror("We actually expected this error - Where is the data for this animation???");
|
||||
Light tempLight;
|
||||
MeshFile->read(&tempLight,16);//2xshort + vector3df
|
||||
ReadABlock(tempLight.AmbientColor,ABDT_FLOAT,3);
|
||||
ReadABlock(tempLight.AmbientIntensity,ABDT_FLOAT,1);
|
||||
ReadABlock(tempLight.DiffuseColor,ABDT_FLOAT,3);
|
||||
ReadABlock(tempLight.DiffuseIntensity,ABDT_FLOAT,1);
|
||||
ReadABlock(tempLight.AttenuationStart,ABDT_FLOAT,1);
|
||||
ReadABlock(tempLight.AttenuationEnd,ABDT_FLOAT,1);
|
||||
ReadABlock(tempLight.Unknown,ABDT_INT,1);
|
||||
M2MLights.push_back(tempLight);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AnimFile = MeshFile;
|
||||
}
|
||||
for(u32 j=0; j<M2MBones.size(); j++)
|
||||
{
|
||||
if(M2MBones[j].translation.header.TimeStamp.num>i && M2MBones[j].translation.header.Values.num>i)
|
||||
{
|
||||
//Timestamps
|
||||
MeshFile->seek(M2MBones[j].translation.header.TimeStamp.ofs+8*i);
|
||||
MeshFile->read(&tempBoneNumOfs, sizeof(numofs));
|
||||
if(tempBoneNumOfs.num > 0)
|
||||
{
|
||||
AnimFile->seek(tempBoneNumOfs.ofs);
|
||||
for(u32 k=0; k<tempBoneNumOfs.num;k++)
|
||||
{
|
||||
AnimFile->read(&tempBoneTS, sizeof(u32));
|
||||
M2MBones[j].translation.timestamps.push_back(tempBoneTS+M2MAnimations[i].start);//Bit of a HACK squash Multitimeline into single timeline.
|
||||
}
|
||||
}
|
||||
//Values
|
||||
MeshFile->seek(M2MBones[j].translation.header.Values.ofs+8*i);
|
||||
MeshFile->read(&tempBoneNumOfs, sizeof(numofs));
|
||||
if(tempBoneNumOfs.num > 0)
|
||||
{
|
||||
AnimFile->seek(tempBoneNumOfs.ofs);
|
||||
for(u32 k=0; k<tempBoneNumOfs.num*3;k++)
|
||||
{
|
||||
AnimFile->read(&tempBoneValue, sizeof(float));
|
||||
M2MBones[j].translation.values.push_back(tempBoneValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(M2MBones[j].rotation.header.TimeStamp.num>i && M2MBones[j].rotation.header.Values.num>i)
|
||||
{
|
||||
//Timestamps
|
||||
MeshFile->seek(M2MBones[j].rotation.header.TimeStamp.ofs+8*i);
|
||||
MeshFile->read(&tempBoneNumOfs, sizeof(numofs));
|
||||
if(tempBoneNumOfs.num > 0)
|
||||
{
|
||||
AnimFile->seek(tempBoneNumOfs.ofs);
|
||||
for(u32 k=0; k<tempBoneNumOfs.num;k++)
|
||||
{
|
||||
AnimFile->read(&tempBoneTS, sizeof(u32));
|
||||
M2MBones[j].rotation.timestamps.push_back(tempBoneTS+M2MAnimations[i].start);//Bit of a HACK squash Multitimeline into single timeline.
|
||||
}
|
||||
}
|
||||
//Values
|
||||
MeshFile->seek(M2MBones[j].rotation.header.Values.ofs+8*i);
|
||||
MeshFile->read(&tempBoneNumOfs, sizeof(numofs));
|
||||
if(tempBoneNumOfs.num > 0)
|
||||
{
|
||||
AnimFile->seek(tempBoneNumOfs.ofs);
|
||||
for(u32 k=0; k<tempBoneNumOfs.num*4;k++)
|
||||
{
|
||||
AnimFile->read(&tempBoneShort, sizeof(s16));
|
||||
tempBoneValue=(tempBoneShort>0?tempBoneShort-32767:tempBoneShort+32767)/32767.0f;
|
||||
M2MBones[j].rotation.values.push_back(tempBoneValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(M2MBones[j].scaling.header.TimeStamp.num>i && M2MBones[j].scaling.header.Values.num>i)
|
||||
{
|
||||
//Timestamps
|
||||
MeshFile->seek(M2MBones[j].scaling.header.TimeStamp.ofs+8*i);
|
||||
MeshFile->read(&tempBoneNumOfs, sizeof(numofs));
|
||||
if(tempBoneNumOfs.num > 0)
|
||||
{
|
||||
AnimFile->seek(tempBoneNumOfs.ofs);
|
||||
for(u32 k=0; k<tempBoneNumOfs.num;k++)
|
||||
{
|
||||
AnimFile->read(&tempBoneTS, sizeof(u32));
|
||||
M2MBones[j].scaling.timestamps.push_back(tempBoneTS+M2MAnimations[i].start);//Bit of a HACK squash Multitimeline into single timeline.
|
||||
}
|
||||
}
|
||||
//Values
|
||||
MeshFile->seek(M2MBones[j].scaling.header.Values.ofs+8*i);
|
||||
MeshFile->read(&tempBoneNumOfs, sizeof(numofs));
|
||||
if(tempBoneNumOfs.num > 0)
|
||||
{
|
||||
AnimFile->seek(tempBoneNumOfs.ofs);
|
||||
for(u32 k=0; k<tempBoneNumOfs.num*3;k++)
|
||||
{
|
||||
AnimFile->read(&tempBoneValue, sizeof(float));
|
||||
M2MBones[j].scaling.values.push_back(tempBoneValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(use_animfile)
|
||||
{
|
||||
AnimFile->drop();
|
||||
}
|
||||
AnimFile=0;
|
||||
}
|
||||
DEBUG(logdebug("Read %u Bones",M2MBones.size()));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -476,6 +390,26 @@ void CM2MeshFileLoader::ReadAnimationData()
|
||||
tempAnimation.start = laststart;
|
||||
tempAnimation.end = laststart + tempRaw.length;
|
||||
laststart += tempRaw.length + 1000;
|
||||
if((tempAnimation.flags & 0x20) == 0)
|
||||
{
|
||||
std::string AnimName = MeshFile->getFileName().c_str();
|
||||
c8 ext[13];
|
||||
sprintf(ext,"%04d-%02d.anim",tempAnimation.animationID,tempAnimation.subanimationID);
|
||||
AnimName = AnimName.substr(0, AnimName.length()-3) + ext;
|
||||
io::IReadFile* AnimFile = io::IrrCreateIReadFileBasic(Device, AnimName.c_str());
|
||||
if (!AnimFile)
|
||||
{
|
||||
logerror("Error! Anim file not found: %s", AnimName.c_str());
|
||||
if(tempAnimation.flags & 0x40)
|
||||
{
|
||||
logerror("We actually expected this error - Where is the data for this animation???");
|
||||
}
|
||||
AnimFile=0;
|
||||
}
|
||||
M2MAnimfiles.push_back(AnimFile);
|
||||
}
|
||||
else
|
||||
M2MAnimfiles.push_back(0);
|
||||
}
|
||||
M2MAnimations.push_back(tempAnimation);
|
||||
DEBUG(logdebug("Animation %u Id %u Start %u End %u",i,tempAnimation.animationID,tempAnimation.start,tempAnimation.end));
|
||||
@ -563,13 +497,13 @@ void CM2MeshFileLoader::ReadTextureDefinitions()
|
||||
|
||||
bool CM2MeshFileLoader::load()
|
||||
{
|
||||
DEBUG(logdebug("Trying to open file %s",MeshFile->getFileName()));
|
||||
DEBUG(logdebug("Trying to open file %s",MeshFile->getFileName().c_str()));
|
||||
|
||||
MeshFile->read(&header,20);
|
||||
DEBUG(logdebug("M2 Version %X",header.version));
|
||||
MeshFile->read(&header,20);
|
||||
DEBUG(logdebug("M2 Version %X",header.version));
|
||||
|
||||
switch(header.version)
|
||||
{
|
||||
switch(header.version)
|
||||
{
|
||||
case 0x100:
|
||||
case 0x104://NEED CHECK
|
||||
case 0x105://NEED CHECK
|
||||
@ -580,12 +514,7 @@ switch(header.version)
|
||||
MeshFile->seek(header.Views.ofs);
|
||||
MeshFile->read(¤tView,sizeof(ModelView));
|
||||
ReadViewData(MeshFile);
|
||||
ReadVertices();
|
||||
|
||||
ReadTextureDefinitions();
|
||||
ReadAnimationData();
|
||||
|
||||
ReadBones();
|
||||
break;
|
||||
}
|
||||
case 0x108:
|
||||
@ -609,12 +538,6 @@ switch(header.version)
|
||||
ReadViewData(SkinFile);
|
||||
SkinFile->drop();
|
||||
|
||||
ReadVertices();
|
||||
|
||||
ReadTextureDefinitions();
|
||||
ReadAnimationData();
|
||||
|
||||
ReadBonesWOTLK();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -622,7 +545,14 @@ switch(header.version)
|
||||
logerror("M2: [%s] Wrong header %0X! File version doesn't match or file is not a M2 file.",MeshFile->getFileName().c_str(),header.version);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
ReadVertices();
|
||||
|
||||
ReadTextureDefinitions();
|
||||
ReadAnimationData();
|
||||
|
||||
ReadBones();
|
||||
ReadColors();
|
||||
|
||||
///////////////////////////
|
||||
// EVERYTHING IS READ
|
||||
@ -750,8 +680,20 @@ for(u32 i=0; i < currentView.Submesh.num;i++)//
|
||||
{
|
||||
if(M2MTextureUnit[j].submeshIndex1==i && !M2MTextureFiles[M2MTextureLookup[M2MTextureUnit[j].textureIndex]].empty())//if a texture unit belongs to this submesh
|
||||
{
|
||||
//set vertex colors from colorblock
|
||||
//FIXME: Only the first color is used, no animation!!
|
||||
s16 vColIndex = M2MTextureUnit[j].colorIndex;
|
||||
if(vColIndex != -1)
|
||||
{
|
||||
DEBUG(logdebug("Applying color %f %f %f %f",M2MVertexColor[vColIndex].Colors.values[0],M2MVertexColor[vColIndex].Colors.values[1],M2MVertexColor[vColIndex].Colors.values[2],M2MVertexColor[vColIndex].Alpha.values[0]));
|
||||
video::SColor color = video::SColorf(M2MVertexColor[vColIndex].Colors.values[0],M2MVertexColor[vColIndex].Colors.values[1],M2MVertexColor[vColIndex].Colors.values[2],M2MVertexColor[vColIndex].Alpha.values[0]).toSColor();
|
||||
// Device->getSceneManager()->getMeshManipulator()->apply(scene::SVertexColorSetManipulator(color), MeshBuffer);//
|
||||
//MeshBuffer->getMaterial().DiffuseColor = color; // if we want to set diffuse instead of vertex color
|
||||
}
|
||||
// get and set texture
|
||||
char buf[1000];
|
||||
MemoryDataHolder::MakeTextureFilename(buf,M2MTextureFiles[M2MTextureLookup[M2MTextureUnit[j].textureIndex]].c_str());
|
||||
|
||||
video::ITexture* tex = Device->getVideoDriver()->findTexture(buf);
|
||||
if(!tex)
|
||||
{
|
||||
@ -764,19 +706,44 @@ for(u32 i=0; i < currentView.Submesh.num;i++)//
|
||||
tex = Device->getVideoDriver()->getTexture(TexFile);
|
||||
TexFile->drop();
|
||||
}
|
||||
MeshBuffer->getMaterial().setTexture(M2MTextureUnit[j].TextureUnitNumber,tex);
|
||||
MeshBuffer->getMaterial().setTexture(M2MTextureUnit[j].TextureUnitNumber,tex); // set a condition here to handle animated textures if they are used irrlicht.sourceforge.net/docu/example008.html
|
||||
|
||||
DEBUG(logdebug("Render Flags: %u %u",M2MRenderFlags[M2MTextureUnit[j].renderFlagsIndex].flags,M2MRenderFlags[M2MTextureUnit[j].renderFlagsIndex].blending));
|
||||
MeshBuffer->getMaterial().BackfaceCulling=(M2MRenderFlags[M2MTextureUnit[j].renderFlagsIndex].flags & 0x04)?false:true;
|
||||
u16 renderflags = M2MRenderFlags[M2MTextureUnit[j].renderFlagsIndex].flags;
|
||||
|
||||
MeshBuffer->getMaterial().Lighting=(renderflags & 0x01)?false:true;
|
||||
MeshBuffer->getMaterial().FogEnable=(renderflags & 0x02)?false:true;
|
||||
MeshBuffer->getMaterial().BackfaceCulling=(renderflags & 0x04)?false:true;
|
||||
//We have a problem here
|
||||
// MeshBuffer->getMaterial().ZBuffer=(renderflags & 0x10)?video::ECFN_LESS:video::ECFN_LESSEQUAL;
|
||||
|
||||
switch(M2MRenderFlags[M2MTextureUnit[j].renderFlagsIndex].blending)
|
||||
{
|
||||
case 1:
|
||||
MeshBuffer->getMaterial().MaterialType=video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF ;
|
||||
case 0: //opaque
|
||||
MeshBuffer->getMaterial().MaterialType=video::EMT_SOLID;
|
||||
break;
|
||||
case 2:
|
||||
case 4:
|
||||
MeshBuffer->getMaterial().MaterialType=video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
DEBUG(logdebug("Alpha Channel Transparency on"));
|
||||
case 1: //alpha ref
|
||||
MeshBuffer->getMaterial().MaterialType=video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; // default REF = 127 maybe set a lower REF?
|
||||
break;
|
||||
case 2: //alpha blend
|
||||
MeshBuffer->getMaterial().MaterialType=video::EMT_ONETEXTURE_BLEND;
|
||||
MeshBuffer->getMaterial().MaterialTypeParam = pack_texureBlendFunc(video::EBF_SRC_ALPHA, video::EBF_ONE_MINUS_SRC_ALPHA, video::EMFN_MODULATE_1X, video::EAS_TEXTURE|video::EAS_VERTEX_COLOR);
|
||||
break;
|
||||
case 3: //additive
|
||||
MeshBuffer->getMaterial().MaterialType=video::EMT_ONETEXTURE_BLEND;
|
||||
MeshBuffer->getMaterial().MaterialTypeParam = pack_texureBlendFunc(video::EBF_SRC_COLOR, video::EBF_DST_COLOR, video::EMFN_MODULATE_1X, video::EAS_TEXTURE|video::EAS_VERTEX_COLOR); // | video::EAS_VERTEX_COLOR);
|
||||
break;
|
||||
case 4: //additive alpha
|
||||
MeshBuffer->getMaterial().MaterialType=video::EMT_ONETEXTURE_BLEND;
|
||||
MeshBuffer->getMaterial().MaterialTypeParam = pack_texureBlendFunc(video::EBF_SRC_ALPHA, video::EBF_ONE, video::EMFN_MODULATE_2X, video::EAS_TEXTURE|video::EAS_VERTEX_COLOR);
|
||||
break;
|
||||
case 5: //modulate blend
|
||||
MeshBuffer->getMaterial().MaterialType=video::EMT_ONETEXTURE_BLEND;
|
||||
MeshBuffer->getMaterial().MaterialTypeParam = pack_texureBlendFunc(video::EBF_SRC_COLOR, video::EBF_DST_COLOR, video::EMFN_MODULATE_1X, video::EAS_TEXTURE|video::EAS_VERTEX_COLOR);
|
||||
break;
|
||||
case 6: //Lumirion: not sure exatly so I'm using modulate2x blend like wowmodelviewer or could use EMT_TRANSPARENT_ADD_COLOR
|
||||
MeshBuffer->getMaterial().MaterialType=video::EMT_ONETEXTURE_BLEND;
|
||||
MeshBuffer->getMaterial().MaterialTypeParam = pack_texureBlendFunc(video::EBF_DST_COLOR, video::EBF_SRC_COLOR, video::EMFN_MODULATE_2X, video::EAS_TEXTURE|video::EAS_VERTEX_COLOR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -792,6 +759,14 @@ for(u32 i=0; i < currentView.Submesh.num;i++)//
|
||||
}
|
||||
Device->getSceneManager()->getMeshManipulator()->flipSurfaces(AnimatedMesh);
|
||||
|
||||
for(u32 i=0; i< M2MAnimfiles.size();i++)
|
||||
{
|
||||
if(M2MAnimfiles[i]!=0)
|
||||
M2MAnimfiles[i]->drop();
|
||||
}
|
||||
|
||||
M2MAnimations.clear();
|
||||
M2MAnimfiles.clear();
|
||||
M2MTriangles.clear();
|
||||
M2Vertices.clear();
|
||||
M2Indices.clear();
|
||||
@ -803,6 +778,8 @@ M2MTextureDef.clear();
|
||||
M2MSubmeshes.clear();
|
||||
M2MTextureFiles.clear();
|
||||
M2MTextureLookup.clear();
|
||||
M2MVertexColor.clear();
|
||||
M2MLights.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -10,6 +10,12 @@ namespace irr
|
||||
namespace scene
|
||||
{
|
||||
|
||||
enum ABlockDatatype{
|
||||
ABDT_FLOAT,
|
||||
ABDT_SHORT,
|
||||
ABDT_INT
|
||||
};
|
||||
|
||||
struct numofs {
|
||||
u32 num;
|
||||
u32 ofs;
|
||||
@ -182,6 +188,24 @@ struct Bone{
|
||||
core::vector3df PivotPoint;
|
||||
};
|
||||
|
||||
struct VertexColor{
|
||||
AnimBlock Colors;
|
||||
AnimBlock Alpha;
|
||||
};
|
||||
|
||||
|
||||
struct Light{
|
||||
u16 Type;
|
||||
s16 Bone;
|
||||
core::vector3df Position;
|
||||
AnimBlock AmbientColor;
|
||||
AnimBlock AmbientIntensity;
|
||||
AnimBlock DiffuseColor;
|
||||
AnimBlock DiffuseIntensity;
|
||||
AnimBlock AttenuationStart;
|
||||
AnimBlock AttenuationEnd;
|
||||
AnimBlock Unknown;
|
||||
};
|
||||
|
||||
class CM2MeshFileLoader : public IMeshLoader
|
||||
{
|
||||
@ -206,11 +230,13 @@ private:
|
||||
|
||||
bool load();
|
||||
void ReadBones();
|
||||
void ReadBonesWOTLK();
|
||||
void ReadColors();
|
||||
void ReadLights();
|
||||
void ReadVertices();
|
||||
void ReadTextureDefinitions();
|
||||
void ReadAnimationData();
|
||||
void ReadViewData(io::IReadFile* file);
|
||||
void ReadABlock(AnimBlock &ABlock, u8 datatype, u8 datanum);
|
||||
|
||||
IrrlichtDevice *Device;
|
||||
core::stringc Texdir;
|
||||
@ -227,6 +253,8 @@ private:
|
||||
SMesh* Mesh;
|
||||
//SSkinMeshBuffer* MeshBuffer;
|
||||
//Taken from the Model file, thus m2M*
|
||||
core::array<Light> M2MLights;
|
||||
core::array<VertexColor> M2MVertexColor;
|
||||
core::array<ModelVertex> M2MVertices;
|
||||
core::array<u16> M2MIndices;
|
||||
core::array<u16> M2MTriangles;
|
||||
@ -238,6 +266,8 @@ private:
|
||||
core::array<RenderFlags> M2MRenderFlags;
|
||||
core::array<u32> M2MGlobalSequences;
|
||||
core::array<Animation> M2MAnimations;
|
||||
core::array<io::IReadFile*> M2MAnimfiles;//Stores pointers to *.anim files in WOTLK
|
||||
|
||||
core::array<s16> M2MAnimationLookup;
|
||||
core::array<Bone> M2MBones;
|
||||
core::array<u16> M2MBoneLookupTable;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user