* 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:
Shlainn 2012-02-16 17:23:44 +01:00
parent b77202fd1c
commit 57e8d3e844
2 changed files with 325 additions and 318 deletions

View File

@ -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(&currentView,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;
}

View File

@ -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;