diff --git a/src/Client/GUI/CM2MeshFileLoader.cpp b/src/Client/GUI/CM2MeshFileLoader.cpp index 3f8f37a..8e7c2f3 100644 --- a/src/Client/GUI/CM2MeshFileLoader.cpp +++ b/src/Client/GUI/CM2MeshFileLoader.cpp @@ -1,4 +1,4 @@ -// #define _DEBUG 1 +#define _DEBUG 1 #include #include "MemoryDataHolder.h" #include "MemoryInterface.h" @@ -47,18 +47,19 @@ IAnimatedMesh* CM2MeshFileLoader::createMesh(io::IReadFile* file) MeshFile = file; AnimatedMesh = new scene::CM2Mesh(); - if ( load() ) - { - AnimatedMesh->finalize(); - } - else - { - AnimatedMesh->drop(); - AnimatedMesh = 0; - } + if ( load() ) + { + AnimatedMesh->finalize(); + } + else + { + AnimatedMesh->drop(); + AnimatedMesh = 0; + } - return AnimatedMesh; + 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 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 + if(!M2MBones.empty()) + { + M2MBones.clear(); + } + MeshFile->seek(header.Bones.ofs); + for(u32 i=0;iread(&tempBone,12+(header.version==0x100?0:4)); + + 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())); -//Bones. This is global data -Bone tempBone; -if(!M2MBones.empty()) -{ - M2MBones.clear(); } -MeshFile->seek(header.Bones.ofs); -for(u32 i=0;iread(&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)); - - 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; -float tempBoneValue; -for(u32 i=0; i0) + if (!M2MVertexColor.empty()) { - MeshFile->seek(M2MBones[i].translation.header.TimeStamp.ofs); - for(u32 j=0; jread(&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;iseek(M2MBones[i].rotation.header.TimeStamp.ofs); - for(u32 j=0; jread(&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; jread(&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; jread(&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=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; jread(&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;iread(&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 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; igetFileName().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) + for(u32 i=0;iread(&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); } - } - else - { - AnimFile = MeshFile; - } - for(u32 j=0; ji && 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; kread(&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; kread(&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; kread(&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; kread(&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; kread(&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; kread(&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,66 +497,62 @@ 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) -{ - case 0x100: - case 0x104://NEED CHECK - case 0x105://NEED CHECK - case 0x106://NEED CHECK - case 0x107://NEED CHECK + switch(header.version) { - MeshFile->read((u8*)&header+20,sizeof(ModelHeader)-20); - MeshFile->seek(header.Views.ofs); - MeshFile->read(¤tView,sizeof(ModelView)); - ReadViewData(MeshFile); - ReadVertices(); - - ReadTextureDefinitions(); - ReadAnimationData(); - - ReadBones(); - break; - } - 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().c_str(); - 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) + case 0x100: + case 0x104://NEED CHECK + case 0x105://NEED CHECK + case 0x106://NEED CHECK + case 0x107://NEED CHECK { - logerror("Error! Skin file not found: %s", SkinName.c_str()); - return 0; + MeshFile->read((u8*)&header+20,sizeof(ModelHeader)-20); + MeshFile->seek(header.Views.ofs); + MeshFile->read(¤tView,sizeof(ModelView)); + ReadViewData(MeshFile); + + break; } - SkinFile->seek(4); // Header of Skin Files is always SKIN - SkinFile->read(¤tView,sizeof(ModelView)); - ReadViewData(SkinFile); - SkinFile->drop(); + 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 - ReadVertices(); + std::string SkinName = MeshFile->getFileName().c_str(); + 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; + } + SkinFile->seek(4); // Header of Skin Files is always SKIN + SkinFile->read(¤tView,sizeof(ModelView)); + ReadViewData(SkinFile); + SkinFile->drop(); - ReadTextureDefinitions(); - ReadAnimationData(); - - ReadBonesWOTLK(); - break; + break; + } + default: + { + 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; + } } - default: - { - 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 @@ -677,9 +607,9 @@ for(u32 i=0;iaddScaleKey(Joint); - scale->frame=M2MBones[i].scaling.timestamps[j]; - scale->scale=core::vector3df(M2MBones[i].scaling.values[j*3],M2MBones[i].scaling.values[j*3+1],M2MBones[i].scaling.values[j*3+2]); + scene::CM2Mesh::SScaleKey* scale=AnimatedMesh->addScaleKey(Joint); + scale->frame=M2MBones[i].scaling.timestamps[j]; + scale->scale=core::vector3df(M2MBones[i].scaling.values[j*3],M2MBones[i].scaling.values[j*3+1],M2MBones[i].scaling.values[j*3+2]); } } @@ -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,20 +706,45 @@ 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 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; - case 2: - case 4: - MeshBuffer->getMaterial().MaterialType=video::EMT_TRANSPARENT_ALPHA_CHANNEL; - DEBUG(logdebug("Alpha Channel Transparency on")); - 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; } diff --git a/src/Client/GUI/CM2MeshFileLoader.h b/src/Client/GUI/CM2MeshFileLoader.h index 098867c..eeaf4a2 100644 --- a/src/Client/GUI/CM2MeshFileLoader.h +++ b/src/Client/GUI/CM2MeshFileLoader.h @@ -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 M2MLights; + core::array M2MVertexColor; core::array M2MVertices; core::array M2MIndices; core::array M2MTriangles; @@ -238,6 +266,8 @@ private: core::array M2MRenderFlags; core::array M2MGlobalSequences; core::array M2MAnimations; + core::array M2MAnimfiles;//Stores pointers to *.anim files in WOTLK + core::array M2MAnimationLookup; core::array M2MBones; core::array M2MBoneLookupTable;