From 1a79b45b990eb123e8edb85c54f48e6764c69591 Mon Sep 17 00:00:00 2001 From: shlainn Date: Sun, 6 Apr 2008 02:25:24 +0000 Subject: [PATCH] M2MeshFile loader 0.2 -Texturing (one layer only) -alpha transparency and backface culling flags handled -various fixes --- src/Client/GUI/CM2MeshFileLoader.cpp | 445 +++++++++++++++++---------- src/Client/GUI/CM2MeshFileLoader.h | 350 ++++++++++++--------- 2 files changed, 486 insertions(+), 309 deletions(-) diff --git a/src/Client/GUI/CM2MeshFileLoader.cpp b/src/Client/GUI/CM2MeshFileLoader.cpp index b5ee476..cee3335 100644 --- a/src/Client/GUI/CM2MeshFileLoader.cpp +++ b/src/Client/GUI/CM2MeshFileLoader.cpp @@ -1,158 +1,287 @@ -#include -#include "CM2MeshFileLoader.h" - -namespace irr -{ - namespace scene - { - - CM2MeshFileLoader::CM2MeshFileLoader(IrrlichtDevice* device):Device(device) - { - - } - - CM2MeshFileLoader::~CM2MeshFileLoader() - { - - } - - - bool CM2MeshFileLoader::isALoadableFileExtension(const c8* filename)const - { - return strstr(filename, ".m2")!=0; - } - - - //! creates/loads an animated mesh from the file. - //! \return Pointer to the created mesh. Returns 0 if loading failed. - //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). - //! See IUnknown::drop() for more information. - IAnimatedMesh* CM2MeshFileLoader::createMesh(io::IReadFile* file) - { - ILogger* logger =Device->getLogger(); - - logger->log("Trying to open file",file->getFileName(),ELL_INFORMATION); - - - file->read(&header,sizeof(ModelHeader)); - if (header.version[0] != 4 && header.version[1] != 1 && header.version[2] != 0 && header.version[3] != 0) { - logger->log("Something wrong!",ELL_ERROR); - return 0; - } - else logger->log(L"header okay",ELL_INFORMATION); - //Name -> not very important I think, but save it nontheless; - std::cout << "Name offset:" << header.nameOfs << "Name length:" << header.nameLength << "\n"; - file->seek(header.nameOfs); - file->read(&M2MeshName[0],header.nameLength); - std::cout << "Read name:"<log("Mesh Name",M2MeshName.c_str(),ELL_INFORMATION); - //Now we load all kinds of data from the file - - //Vertices - if(!M2MVertices.empty()) - M2MVertices.clear(); - - ModelVertex tempM2MVert; - file->seek(header.ofsVertices); - - for(u32 i =0;iread(&tempM2MVert,sizeof(ModelVertex)); - M2MVertices.push_back(tempM2MVert); - } - std::cout << "Read "<0) - M2MViews.clear(); - ModelView tempM2MView; - file->seek(header.ofsViews); - for(u32 i =0;iread(&tempM2MView,sizeof(ModelView)); - M2MViews.push_back(tempM2MView); - } - std::cout << "Read "<log("Using View 0 for all further operations",ELL_INFORMATION); - - //Vertex indices of a specific view. - if(M2MIndices.size()>0) - M2MIndices.clear(); - - u16 tempM2Index; - file->seek(M2MViews[0].ofsIndex); - for(u32 i =0;iread(&tempM2Index,sizeof(u16)); - M2MIndices.push_back(tempM2Index); - } - std::cout << "Read "<0) - M2MTriangles.clear(); - - u16 tempM2Triangle; - file->seek(M2MViews[0].ofsTris); - for(u32 i =0;iread(&tempM2Triangle,sizeof(u16)); - M2MTriangles.push_back(tempM2Triangle); - } - std::cout << "Read "<seek(header.ofsTexLookup); - for(u32 i=0;i0) - M2Vertices.clear(); - - for(u32 i=0;i0) - M2Indices.clear(); - - for(u32 i=0;igetMeshBufferCount()>0) - { - Mesh->MeshBuffers.erase(0); - } - - std::cout << "Sending "<append(M2Vertices.const_pointer(),M2Vertices.size(),M2Indices.const_pointer(),M2Indices.size()); - - IMB->recalculateBoundingBox(); - Mesh->addMeshBuffer(IMB); - IMB->drop(); - aniMesh= new SAnimatedMesh(); - - - aniMesh->addMesh(Mesh); - Mesh->drop(); - Mesh = 0; - - aniMesh->recalculateBoundingBox(); - - return aniMesh; - } - - } -} +#include +#include "CM2MeshFileLoader.h" + + + +namespace irr +{ +namespace scene +{ + +CM2MeshFileLoader::CM2MeshFileLoader(IrrlichtDevice* device, c8* basedir):Device(device), Basedir(basedir) +{ + +} + +CM2MeshFileLoader::~CM2MeshFileLoader() +{ + +} + + +bool CM2MeshFileLoader::isALoadableFileExtension(const c8* filename)const +{ + return strstr(filename, ".m2")!=0; +} + + +//! creates/loads an animated mesh from the file. +//! \return Pointer to the created mesh. Returns 0 if loading failed. +//! If you no longer need the mesh, you should call IAnimatedMesh::drop(). +//! See IUnknown::drop() for more information. +IAnimatedMesh* CM2MeshFileLoader::createMesh(io::IReadFile* file) +{ +ILogger* logger =Device->getLogger(); + +logger->log("Trying to open file",file->getFileName(),ELL_INFORMATION); + + +file->read(&header,sizeof(ModelHeader)); + if (header.version[0] != 4 && header.version[1] != 1 && header.version[2] != 0 && header.version[3] != 0) { + logger->log("Something wrong!",ELL_ERROR); + return 0; + } + else logger->log(L"header okay",ELL_INFORMATION); +//Name -> not very important I think, but save it nontheless; +std::cout << "Name offset:" << header.nameOfs << "Name length:" << header.nameLength << "\n"; +//M2MeshName.clear(); +//M2MeshName.reserve(header.nameLength); +file->seek(header.nameOfs); +// file->read(&M2MeshName[0],header.nameLength); +//std::cout << "Read name:"<log("Mesh Name",M2MeshName.c_str(),ELL_INFORMATION); +//Now we load all kinds of data from the file + +//Vertices. Global data +if(!M2MVertices.empty()) + M2MVertices.clear(); + +ModelVertex tempM2MVert; +file->seek(header.ofsVertices); + +for(u32 i =0;iread(&tempM2MVert,sizeof(ModelVertex)); + M2MVertices.push_back(tempM2MVert); +} +std::cout << "Read "<0) + M2MViews.clear(); +ModelView tempM2MView; +file->seek(header.ofsViews); +for(u32 i =0;iread(&tempM2MView,sizeof(ModelView)); + M2MViews.push_back(tempM2MView); +} +std::cout << "Read "<log("Using View 0 for all further operations",ELL_INFORMATION); +std::cout<<"This View has "<0) + M2MIndices.clear(); + +u16 tempM2Index; +file->seek(M2MViews[0].ofsIndex); +for(u32 i =0;iread(&tempM2Index,sizeof(u16)); + M2MIndices.push_back(tempM2Index); +} +std::cout << "Read "<0) + M2MTriangles.clear(); + +u16 tempM2Triangle; +file->seek(M2MViews[0].ofsTris); +for(u32 i =0;iread(&tempM2Triangle,sizeof(u16)); + M2MTriangles.push_back(tempM2Triangle); +} +std::cout << "Read "<0) + M2MSubmeshes.clear(); + +ModelViewSubmesh tempM2Submesh; +file->seek(M2MViews[0].ofsSub); +for(u32 i =0;iread(&tempM2Submesh,sizeof(ModelViewSubmesh)); + M2MSubmeshes.push_back(tempM2Submesh); +// std::cout<< "Submesh " <seek(M2MViews[0].ofsTex); +for(u32 i=0;iread(&tempM2TexUnit,sizeof(TextureUnit)); + M2MTextureUnit.push_back(tempM2TexUnit); +} +std::cout << "Read "<seek(header.ofsTexLookup); +for(u32 i=0;iread(&tempM2TexLookup,sizeof(u16)); + M2MTextureLookup.push_back(tempM2TexLookup); +} +std::cout << "Read "<seek(header.ofsTextures); +for(u32 i=0;iread(&tempM2TexDef,sizeof(TextureDefinition)); + M2MTextureDef.push_back(tempM2TexDef); +} +std::cout << "Read "<seek(header.ofsTexFlags); +for(u32 i=0;iread(&tempM2RF,sizeof(RenderFlags)); + M2MRenderFlags.push_back(tempM2RF); +} +std::cout << "Read "<seek(M2MTextureDef[i].texFileOfs); + file->read(&tempTexFileName[0],M2MTextureDef[i].texFileLen); + M2MTextureFiles.push_back(tempTexFileName.c_str()); + std::cout<0) + M2Vertices.clear(); + +for(u32 i=0;idrop(); + +Mesh=new SMesh(); + + +while(Mesh->getMeshBufferCount()>0) +{ + Mesh->MeshBuffers.erase(0); +} + + +for(u32 i=0; i < M2MViews[0].nSub;i++)// +{ +//std::cout << "Proceeding with Submesh "<0) + M2Indices.clear(); + +for(u32 j=M2MSubmeshes[i].ofsTris;jappend(M2Vertices.const_pointer(),M2Vertices.size(),M2Indices.const_pointer(),M2Indices.size()); +IMB->recalculateBoundingBox(); + +//IMB->getMaterial().DiffuseColor.set(255,255-(u32)(255/(M2MSubmeshes.size()))*i,(u32)(255/(M2MSubmeshes.size()))*i,0); +//IMB->getMaterial().DiffuseColor.set(255,(M2MSubmeshes[i].meshpartId==0?0:255),(M2MSubmeshes[i].meshpartId==0?255:0),0); + + +std::string TexName=Basedir.c_str(); +TexName+="/"; +TexName+=M2MTextureFiles[M2MTextureUnit[i].textureIndex].c_str(); + +while(TexName.find('\\')getMaterial().setTexture(0,Device->getVideoDriver()->getTexture(TexName.c_str())); +std::cout<getMaterial().BackfaceCulling=(M2MRenderFlags[i].flags & 0x04)?false:true; +if(M2MRenderFlags[i].blending==1) + IMB->getMaterial().MaterialType=video::EMT_TRANSPARENT_ALPHA_CHANNEL; + Mesh->addMeshBuffer(IMB); +IMB->drop(); +//std::cout << "Mesh now has "<getMeshBufferCount()<<" Buffers\n"; +} + +aniMesh= new SAnimatedMesh(); +aniMesh->addMesh(Mesh); +Mesh->drop(); +Mesh = 0; + +aniMesh->recalculateBoundingBox(); + + +return aniMesh; +} + +} +} diff --git a/src/Client/GUI/CM2MeshFileLoader.h b/src/Client/GUI/CM2MeshFileLoader.h index afbd47d..a856aa0 100644 --- a/src/Client/GUI/CM2MeshFileLoader.h +++ b/src/Client/GUI/CM2MeshFileLoader.h @@ -1,151 +1,199 @@ -#include "irrlicht/irrlicht.h" -#include "irrlicht/IMeshLoader.h" - - -namespace irr -{ - namespace scene - { - - class CM2MeshFileLoader : public IMeshLoader - { - public: - - //! Constructor - CM2MeshFileLoader(IrrlichtDevice* device); - - //! destructor - ~CM2MeshFileLoader(); - - //! returns true if the file maybe is able to be loaded by this class - //! based on the file extension (e.g. ".cob") - virtual bool isALoadableFileExtension(const c8* fileName) const; - - //! creates/loads an animated mesh from the file. - //! \return Pointer to the created mesh. Returns 0 if loading failed. - //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). - //! See IUnknown::drop() for more information. - virtual scene::IAnimatedMesh* createMesh(irr::io::IReadFile* file); - private: - - - struct ModelHeader { - c8 id[4]; - u8 version[4]; - u32 nameLength; - u32 nameOfs; - u32 type; - - u32 nGlobalSequences; - u32 ofsGlobalSequences; - u32 nAnimations; - u32 ofsAnimations; - u32 nC; - u32 ofsC; - u32 nD; - u32 ofsD; - u32 nBones; - u32 ofsBones; - u32 nF; - u32 ofsF; - - u32 nVertices; - u32 ofsVertices; - u32 nViews; - u32 ofsViews; - - u32 nColors; - u32 ofsColors; - - u32 nTextures; - u32 ofsTextures; - - u32 nTransparency; // H - u32 ofsTransparency; - u32 nI; // always unused ? - u32 ofsI; - u32 nTexAnims; // J - u32 ofsTexAnims; - u32 nTexReplace; - u32 ofsTexReplace; - - u32 nTexFlags; - u32 ofsTexFlags; - u32 nY; - u32 ofsY; - - u32 nTexLookup; - u32 ofsTexLookup; - - u32 nTexUnitLookup; // L - u32 ofsTexUnitLookup; - u32 nTransparencyLookup; // M - u32 ofsTransparencyLookup; - u32 nTexAnimLookup; - u32 ofsTexAnimLookup; - - f32 floats[14]; - - u32 nBoundingTriangles; - u32 ofsBoundingTriangles; - u32 nBoundingVertices; - u32 ofsBoundingVertices; - u32 nBoundingNormals; - u32 ofsBoundingNormals; - - u32 nAttachments; // O - u32 ofsAttachments; - u32 nAttachLookup; // P - u32 ofsAttachLookup; - u32 nQ; // Q - u32 ofsQ; - u32 nLights; // R - u32 ofsLights; - u32 nCameras; // S - u32 ofsCameras; - u32 nT; - u32 ofsT; - u32 nRibbonEmitters; // U - u32 ofsRibbonEmitters; - u32 nParticleEmitters; // V - u32 ofsParticleEmitters; - - } header; - - - struct ModelVertex { - core::vector3df pos;//Use Irrlicht Vector here! - u8 weights[4]; - u8 bones[4]; - core::vector3df normal;//Use Irrlicht Vector here! - core::vector2df texcoords;//Use Irrlicht Vector here! - u32 unk1, unk2; // always 0,0 so this is probably unused - }; - - struct ModelView { - u32 nIndex, ofsIndex; // Vertices in this model (index into vertices[]) - u32 nTris, ofsTris; // indices - u32 nProps, ofsProps; // additional vtx properties - u32 nSub, ofsSub; // materials/renderops/submeshes - u32 nTex, ofsTex; // material properties/textures - s32 lod; // LOD bias? - }; - - // io::IFileSystem* FileSystem; - IrrlichtDevice* Device; - // scene::IMeshManipulator* Manipulator; - core::stringc M2MeshName; - SAnimatedMesh* aniMesh; - SMesh* Mesh; - //Taken from the Model file, thus m2M* - core::array M2MVertices; - core::array M2MViews; - core::array M2MIndices; - core::array M2MTriangles; - //Used for the Mesh, thus m2_noM_* - core::array M2Vertices; - core::array M2Indices; - - }; - }//namespace scene -}//namespace irr +#include "irrlicht/irrlicht.h" +#include "irrlicht/IMeshLoader.h" +#include +#include + +namespace irr +{ +namespace scene +{ + +class CM2MeshFileLoader : public IMeshLoader +{ +public: + + //! Constructor + CM2MeshFileLoader(IrrlichtDevice* device, c8* basedir); + + //! destructor + virtual ~CM2MeshFileLoader(); + + //! returns true if the file maybe is able to be loaded by this class + //! based on the file extension (e.g. ".cob") + virtual bool isALoadableFileExtension(const c8* fileName)const; + + //! creates/loads an animated mesh from the file. + //! \return Pointer to the created mesh. Returns 0 if loading failed. + //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). + //! See IUnknown::drop() for more information. + virtual scene::IAnimatedMesh* createMesh(irr::io::IReadFile* file); +private: + + +struct ModelHeader { + c8 id[4]; + u8 version[4]; + u32 nameLength; + u32 nameOfs; + u32 type; + + u32 nGlobalSequences; + u32 ofsGlobalSequences; + u32 nAnimations; + u32 ofsAnimations; + u32 nC; + u32 ofsC; + u32 nD; + u32 ofsD; + u32 nBones; + u32 ofsBones; + u32 nF; + u32 ofsF; + + u32 nVertices; + u32 ofsVertices; + u32 nViews; + u32 ofsViews; + + u32 nColors; + u32 ofsColors; + + u32 nTextures; + u32 ofsTextures; + + u32 nTransparency; // H + u32 ofsTransparency; + u32 nI; // always unused ? + u32 ofsI; + u32 nTexAnims; // J + u32 ofsTexAnims; + u32 nTexReplace; + u32 ofsTexReplace; + + u32 nTexFlags; + u32 ofsTexFlags; + u32 nY; + u32 ofsY; + + u32 nTexLookup; + u32 ofsTexLookup; + + u32 nTexUnitLookup; // L + u32 ofsTexUnitLookup; + u32 nTransparencyLookup; // M + u32 ofsTransparencyLookup; + u32 nTexAnimLookup; + u32 ofsTexAnimLookup; + + f32 floats[14]; + + u32 nBoundingTriangles; + u32 ofsBoundingTriangles; + u32 nBoundingVertices; + u32 ofsBoundingVertices; + u32 nBoundingNormals; + u32 ofsBoundingNormals; + + u32 nAttachments; // O + u32 ofsAttachments; + u32 nAttachLookup; // P + u32 ofsAttachLookup; + u32 nQ; // Q + u32 ofsQ; + u32 nLights; // R + u32 ofsLights; + u32 nCameras; // S + u32 ofsCameras; + u32 nT; + u32 ofsT; + u32 nRibbonEmitters; // U + u32 ofsRibbonEmitters; + u32 nParticleEmitters; // V + u32 ofsParticleEmitters; + +} header; + + +struct ModelVertex { + core::vector3df pos;//Use Irrlicht Vector here! + u8 weights[4]; + u8 bones[4]; + core::vector3df normal;//Use Irrlicht Vector here! + core::vector2df texcoords;//Use Irrlicht Vector here! + u32 unk1, unk2; // always 0,0 so this is probably unused +}; + +struct ModelView { + u32 nIndex, ofsIndex; // Vertices in this model (index into vertices[]) + u32 nTris, ofsTris; // indices + u32 nProps, ofsProps; // additional vtx properties + u32 nSub, ofsSub; // materials/renderops/submeshes + u32 nTex, ofsTex; // material properties/textures + s32 lod; // LOD bias? +}; + +struct ModelViewSubmesh { + u32 meshpartId; + u16 ofsVertex;//Starting vertex number for this submesh + u16 nVertex; + u16 ofsTris;//Starting Triangle index + u16 nTris; + u16 unk1, unk2, unk3, unk4; + core::vector3df v; + float unkf[4]; +}; + +struct TextureDefinition { + u32 texType; + u16 unk; + u16 texFlags; + u32 texFileLen; + u32 texFileOfs; +}; + +struct TextureUnit{ + u16 Flags; + s16 renderOrder; + u16 submeshIndex1, submeshIndex2; + s16 colorIndex; + u16 renderFlagsIndex; + u16 TextureUnitNumber; + u16 unk1; + u16 textureIndex; + u16 TextureUnitNumber2; + u16 transparencyIndex; + u16 texAnimIndex; +}; + +struct RenderFlags{ + u16 flags; + u16 blending; +}; + +// + io::IFileSystem* FileSystem; + IrrlichtDevice* Device; +// scene::IMeshManipulator* Manipulator; + core::stringc M2MeshName; + core::stringc Basedir; + SAnimatedMesh* aniMesh; + SMesh* Mesh; + SMeshBuffer* IMB; + //Taken from the Model file, thus m2M* + core::array M2MVertices; + core::array M2MViews; + core::array M2MIndices; + core::array M2MTriangles; + core::array M2MSubmeshes; + core::array M2MTextureLookup; + core::array M2MTextureDef; + core::array M2MTextureFiles; + core::array M2MTextureUnit; + core::array M2MRenderFlags; + //Used for the Mesh, thus m2_noM_* + core::array M2Vertices; + core::array M2Indices; + +}; +}//namespace scene +}//namespace irr