From 7c50899481cb79ab4d9464044d4f803ca7aa9814 Mon Sep 17 00:00:00 2001 From: aramis_acg Date: Tue, 4 Nov 2008 20:41:11 +0000 Subject: [PATCH] Fixed 3DS, ASE, MD3 and Q3D orientation after Schrompf' recent changes to the RH-LH conversion. WIP version of animation support in the 3DS loader. Still hoping to find out why the pivots aren't handled correctly ... Added first draft of a B3D loader provided by Mark Sibly. Moved DeterminePType-Step to ScenePreprocessor. Small LWO fix. Still texturing problems. git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@231 67173fc5-114c-0410-ac8e-9d2fd5bffc1f --- code/3DSConverter.cpp | 129 +++++++++++- code/3DSLoader.cpp | 9 +- code/3DSLoader.h | 3 +- code/ASELoader.cpp | 17 +- code/B3DImporter.cpp | 377 +++++++++++++++++++++++++++++++++++ code/B3DImporter.h | 106 ++++++++++ code/IRRLoader.cpp | 23 +++ code/IRRMeshLoader.cpp | 22 +- code/Importer.cpp | 17 +- code/LWOLoader.cpp | 6 +- code/MD3Loader.cpp | 4 +- code/Q3DLoader.cpp | 4 +- code/ScenePreprocessor.cpp | 36 +++- code/ScenePreprocessor.h | 1 + code/SortByPTypeProcess.cpp | 58 ------ code/SortByPTypeProcess.h | 30 --- code/makefile | 3 +- code/makefile.mingw | 4 +- workspaces/vc8/assimp.vcproj | 12 ++ 19 files changed, 732 insertions(+), 129 deletions(-) create mode 100644 code/B3DImporter.cpp create mode 100644 code/B3DImporter.h diff --git a/code/3DSConverter.cpp b/code/3DSConverter.cpp index c2abf35c9..2aa3513a7 100644 --- a/code/3DSConverter.cpp +++ b/code/3DSConverter.cpp @@ -519,11 +519,13 @@ void Discreet3DSImporter::ConvertMeshes(aiScene* pcOut) // ------------------------------------------------------------------------------------------------ // Add a node to the scenegraph and setup its final transformation -void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Node* pcIn) +void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Node* pcIn, + aiMatrix4x4& absTrafo) { std::vector iArray; iArray.reserve(3); + aiMatrix4x4 abs; if (pcIn->mName == "$$$DUMMY") { // append the "real" name of the dummy to the string @@ -542,11 +544,21 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Nod } if (!iArray.empty()) { + // The matrix should be identical for all meshes. + // It HAS to be identical for all meshes ........ aiMatrix4x4& mTrafo = ((D3DS::Mesh*)pcSOut->mMeshes[iArray[0]]->mColors[0])->mMat; aiMatrix4x4 mInv = mTrafo; if (!configSkipPivot) mInv.Inverse(); + /* abs = mTrafo; + pcOut->mTransformation = absTrafo; + pcOut->mTransformation = pcOut->mTransformation.Inverse() * mTrafo; + const aiVector3D& pivot = pcIn->vPivot; + aiMatrix4x4 trans; + */ + const aiVector3D& pivot = pcIn->vPivot; + pcOut->mNumMeshes = (unsigned int)iArray.size(); pcOut->mMeshes = new unsigned int[iArray.size()]; for (unsigned int i = 0;i < iArray.size();++i) @@ -555,7 +567,6 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Nod aiMesh* const mesh = pcSOut->mMeshes[iIndex]; // http://www.zfx.info/DisplayThread.php?MID=235690#235690 - const aiVector3D& pivot = pcIn->vPivot; const aiVector3D* const pvEnd = mesh->mVertices+mesh->mNumVertices; aiVector3D* pvCurrent = mesh->mVertices; @@ -568,7 +579,6 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Nod pvCurrent->y -= pivot.y; pvCurrent->z -= pivot.z; *pvCurrent = mTrafo * (*pvCurrent); - //std::swap( pvCurrent->y, pvCurrent->z ); ++pvCurrent; } } @@ -577,22 +587,81 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Nod { while (pvCurrent != pvEnd) { - std::swap( pvCurrent->y, pvCurrent->z ); + *pvCurrent = mInv * (*pvCurrent); ++pvCurrent; } } #endif + + // Setup the mesh index pcOut->mMeshes[i] = iIndex; } } } + // Generate animation channels for the node + if (pcIn->aPositionKeys.size() > 0 || pcIn->aRotationKeys.size() > 0 || + pcIn->aScalingKeys.size() > 0 || pcIn->aCameraRollKeys.size() > 0 || + pcIn->aTargetPositionKeys.size() > 0) + { + aiAnimation* anim = pcSOut->mAnimations[0]; + ai_assert(NULL != anim); + + // Allocate a new channel, increment the channel index + aiNodeAnim* channel = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim(); + + // POSITION keys + if (pcIn->aPositionKeys.size() > 0) + { + // Sort all keys with ascending time values + std::sort(pcIn->aPositionKeys.begin(),pcIn->aPositionKeys.end()); + + channel->mNumPositionKeys = (unsigned int)pcIn->aPositionKeys.size(); + channel->mPositionKeys = new aiVectorKey[channel->mNumPositionKeys]; + ::memcpy(channel->mPositionKeys,&pcIn->aPositionKeys[0], + sizeof(aiVectorKey)*channel->mNumPositionKeys); + + // Get the maximum key + anim->mDuration = std::max(anim->mDuration,channel-> + mPositionKeys[channel->mNumPositionKeys-1].mTime); + } + + // ROTATION keys + if (pcIn->aRotationKeys.size() > 0) + { + // Sort all keys with ascending time values + std::sort(pcIn->aRotationKeys.begin(),pcIn->aRotationKeys.end()); + + channel->mNumRotationKeys = (unsigned int)pcIn->aRotationKeys.size(); + channel->mRotationKeys = new aiQuatKey[channel->mNumRotationKeys]; + ::memcpy(channel->mRotationKeys,&pcIn->aRotationKeys[0], + sizeof(aiQuatKey)*channel->mNumRotationKeys); + + // Get the maximum key + anim->mDuration = std::max(anim->mDuration,channel-> + mRotationKeys[channel->mNumRotationKeys-1].mTime); + } + + // SCALING keys + if (pcIn->aScalingKeys.size() > 0) + { + // Sort all keys with ascending time values + std::sort(pcIn->aScalingKeys.begin(),pcIn->aScalingKeys.end()); + + channel->mNumScalingKeys = (unsigned int)pcIn->aScalingKeys.size(); + channel->mScalingKeys = new aiVectorKey[channel->mNumScalingKeys]; + ::memcpy(channel->mScalingKeys,&pcIn->aScalingKeys[0], + sizeof(aiVectorKey)*channel->mNumScalingKeys); + + // Get the maximum key + anim->mDuration = std::max(anim->mDuration,channel-> + mScalingKeys[channel->mNumScalingKeys-1].mTime); + } + } + // Setup the name of the node pcOut->mName.Set(pcIn->mName); - // Setup the transformation matrix of the node - pcOut->mTransformation = aiMatrix4x4(); - // Allocate storage for children pcOut->mNumChildren = (unsigned int)pcIn->mChildren.size(); pcOut->mChildren = new aiNode*[pcIn->mChildren.size()]; @@ -602,11 +671,30 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Nod { pcOut->mChildren[i] = new aiNode(); pcOut->mChildren[i]->mParent = pcOut; - AddNodeToGraph(pcSOut,pcOut->mChildren[i],pcIn->mChildren[i]); + AddNodeToGraph(pcSOut,pcOut->mChildren[i],pcIn->mChildren[i],abs); } return; } +// ------------------------------------------------------------------------------------------------ +// Find out how many node animation channels we'll have finally +void CountTracks(D3DS::Node* node, unsigned int& cnt) +{ + // We will never generate more than one channel for a node, so + // this is rather easy here. + + if (node->aPositionKeys.size() > 0 || node->aRotationKeys.size() > 0 || + node->aScalingKeys.size() > 0 || node->aCameraRollKeys.size() > 0 || + node->aTargetPositionKeys.size() > 0) + { + ++cnt; + } + + // Recursively process all children + for (unsigned int i = 0; i < node->mChildren.size();++i) + CountTracks(node->mChildren[i],cnt); +} + // ------------------------------------------------------------------------------------------------ // Generate the output node graph void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut) @@ -670,9 +758,26 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut) { // First of all: find out how many scaling, rotation and translation // animation tracks we'll have afterwards - //unsigned int numRot = 0, numScale = 0, numTranslate = 0; - //CountTracks(mRootNode,numRot,numScale,numTranslate); - AddNodeToGraph(pcOut, pcOut->mRootNode, mRootNode); + unsigned int numChannel = 0; + CountTracks(mRootNode,numChannel); + + if (numChannel) + { + // Allocate a primary animation channel + pcOut->mNumAnimations = 1; + pcOut->mAnimations = new aiAnimation*[1]; + aiAnimation* anim = pcOut->mAnimations[0] = new aiAnimation(); + + anim->mName.Set("3DSMasterAnim"); + + // Allocate enough storage for all node animation channels, + // but don't set the mNumChannels member - we'll use it to + // index into the array + anim->mChannels = new aiNodeAnim*[numChannel]; + } + + aiMatrix4x4 m; + AddNodeToGraph(pcOut, pcOut->mRootNode, mRootNode,m); } // We used the first vertex color set to store some @@ -694,11 +799,13 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut) if (pcOut->mRootNode->mName.data[0] == '$' && pcOut->mRootNode->mName.data[1] == '$') pcOut->mRootNode->mName.Set(""); +#if 0 // modify the transformation of the root node to change // the coordinate system of the whole scene from Max' to OpenGL pcOut->mRootNode->mTransformation.a3 *= -1.f; pcOut->mRootNode->mTransformation.b3 *= -1.f; pcOut->mRootNode->mTransformation.c3 *= -1.f; +#endif } // ------------------------------------------------------------------------------------------------ diff --git a/code/3DSLoader.cpp b/code/3DSLoader.cpp index e8dbecca5..d19f69332 100644 --- a/code/3DSLoader.cpp +++ b/code/3DSLoader.cpp @@ -566,11 +566,14 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) // (target animation channels are stored with a // separate object ID) D3DS::Node* pcNode = FindNode(mRootNode,name); - if (!pcNode) + if (pcNode) { - pcNode = new D3DS::Node(); - pcNode->mName = name; + // Make this node the current node + mCurrentNode = pcNode; + break; } + pcNode = new D3DS::Node(); + pcNode->mName = name; // There are two unknown values which we can safely ignore stream->IncPtr(4); diff --git a/code/3DSLoader.h b/code/3DSLoader.h index 9a7eea936..28fbde92e 100644 --- a/code/3DSLoader.h +++ b/code/3DSLoader.h @@ -219,7 +219,8 @@ protected: // ------------------------------------------------------------------- /** Add a node to the node graph */ - void AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Node* pcIn); + void AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Node* pcIn, + aiMatrix4x4& absTrafo); // ------------------------------------------------------------------- /** Search for a node in the graph. diff --git a/code/ASELoader.cpp b/code/ASELoader.cpp index 054ed46d6..fe83a3520 100644 --- a/code/ASELoader.cpp +++ b/code/ASELoader.cpp @@ -556,12 +556,15 @@ void ASEImporter::AddNodes (std::vector& nodes, // allocate enough space for the child nodes pcParent->mNumChildren = (unsigned int)apcNodes.size(); - pcParent->mChildren = new aiNode*[apcNodes.size()]; - - // now build all nodes for our nice new children - for (unsigned int p = 0; p < apcNodes.size();++p) + if (pcParent->mNumChildren) { - pcParent->mChildren[p] = apcNodes[p]; + pcParent->mChildren = new aiNode*[apcNodes.size()]; + + // now build all nodes for our nice new children + for (unsigned int p = 0; p < apcNodes.size();++p) + { + pcParent->mChildren[p] = apcNodes[p]; + } } return; } @@ -578,7 +581,7 @@ void ASEImporter::BuildNodes() pcScene->mRootNode->mName.Set(""); // Setup the coordinate system transformation - pcScene->mRootNode->mTransformation.c3 *= -1.f; + //pcScene->mRootNode->mTransformation.c3 *= -1.f; pcScene->mRootNode->mNumChildren = 1; pcScene->mRootNode->mChildren = new aiNode*[1]; pcScene->mRootNode->mChildren[0] = new aiNode(); @@ -744,7 +747,7 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh) if (!mesh.amTexCoords[c].empty()) { amTexCoords[c][iCurrent] = mesh.amTexCoords[c][(*i).amUVIndices[c][n]]; - amTexCoords[c][iCurrent].y = 1.0f - amTexCoords[c][iCurrent].y; // DX-to-OGL + // amTexCoords[c][iCurrent].y = 1.f- amTexCoords[c][iCurrent].y; // DX-to-OGL } } // add vertex colors diff --git a/code/B3DImporter.cpp b/code/B3DImporter.cpp new file mode 100644 index 000000000..bce296d93 --- /dev/null +++ b/code/B3DImporter.cpp @@ -0,0 +1,377 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file Implementation of the b3d importer class */ + +#include "AssimpPCH.h" + +// internal headers +#include "B3DImporter.h" +#include "TextureTransform.h" + +using namespace Assimp; +using namespace std; + +bool B3DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const{ + + int pos=pFile.find_last_of( '.' ); + if( pos==string::npos ) return false; + + string ext=pFile.substr( pos+1 ); + if( ext.size()!=3 ) return false; + + return (ext[0]=='b' || ext[0]=='B') && (ext[1]=='3') && (ext[2]=='d' || ext[2]=='D'); +} + +void B3DImporter::GetExtensionList( std::string& append ){ + append.append("*.b3d"); +} + +void B3DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler){ + + boost::scoped_ptr file( pIOHandler->Open( pFile)); + + // Check whether we can read from the file + if( file.get() == NULL) + throw new ImportErrorException( "Failed to open B3D file " + pFile + "."); + + // check whether the .b3d file is large enough to contain + // at least one chunk. + size_t fileSize = file->FileSize(); + if( fileSize < 8) throw new ImportErrorException( "B3D File is too small."); + + _pos=0; + _buf.resize( fileSize ); + file->Read( &_buf[0],1,fileSize ); + _stack.clear(); + _textures.clear(); + _materials.size(); + _vertices.clear(); + _meshes.clear(); + + ReadBB3D(); + + //materials + aiMaterial **mats=new aiMaterial*[_materials.size()]; + for( unsigned i=0;i<_materials.size();++i ){ + mats[i]=_materials[i]; + } + pScene->mNumMaterials=_materials.size(); + pScene->mMaterials=mats; + + //meshes + aiMesh **meshes=new aiMesh*[_meshes.size()]; + for( unsigned i=0;i<_meshes.size();++i ){ + meshes[i]=_meshes[i]; + } + pScene->mNumMeshes=_meshes.size(); + pScene->mMeshes=meshes; + + //nodes - NOTE: Have to create mMeshes array here or crash 'n' burn. + aiNode *node=new aiNode( "root" ); + node->mNumMeshes=_meshes.size(); + node->mMeshes=new unsigned[_meshes.size()]; + for( unsigned i=0;i<_meshes.size();++i ){ + node->mMeshes[i]=i; + } + pScene->mRootNode=node; +} + +int B3DImporter::ReadByte(){ + if( _pos<_buf.size() ) return _buf[_pos++]; + throw new ImportErrorException( "B3D EOF Error" ); +} + +int B3DImporter::ReadInt(){ + if( _pos+4<=_buf.size() ){ + int n=*(int*)&_buf[_pos]; + _pos+=4; + return n; + } + throw new ImportErrorException( "B3D EOF Error" ); +} + +float B3DImporter::ReadFloat(){ + if( _pos+4<=_buf.size() ){ + float n=*(float*)&_buf[_pos]; + _pos+=4; + return n; + } + throw new ImportErrorException( "B3D EOF Error" ); +} + +B3DImporter::Vec2 B3DImporter::ReadVec2(){ + Vec2 t; + t.x=ReadFloat(); + t.y=ReadFloat(); + return t; +} + +B3DImporter::Vec3 B3DImporter::ReadVec3(){ + Vec3 t; + t.x=ReadFloat(); + t.y=ReadFloat(); + t.z=ReadFloat(); + return t; +} + +B3DImporter::Vec4 B3DImporter::ReadVec4(){ + Vec4 t; + t.x=ReadFloat(); + t.y=ReadFloat(); + t.z=ReadFloat(); + t.w=ReadFloat(); + return t; +} + +string B3DImporter::ReadString(){ + string str; + while( _pos<_buf.size() ){ + char c=(char)ReadByte(); + if( !c ) return str; + str+=c; + } + throw new ImportErrorException( "B3D EOF Error" ); +} + +string B3DImporter::ReadChunk(){ + string tag; + for( int i=0;i<4;++i ){ + tag+=char( ReadByte() ); + } +// cout<<"ReadChunk:"<AddProperty( &texstr,AI_MATKEY_TEXTURE_DIFFUSE(0) ); + } + } + } +} + +void B3DImporter::ReadVRTS(){ + int vertFlags=ReadInt(); + int tc_sets=ReadInt(); + int tc_size=ReadInt(); + + if( tc_sets<0 || tc_sets>4 || tc_size<0 || tc_size>4 ) throw new ImportErrorException( "B3D Param Error" ); + + while( ChunkSize() ){ + Vertex vert; + + vert.position=ReadVec3(); + + if( vertFlags & 1 ){ + vert.normal=ReadVec3(); + } + + if( vertFlags & 2 ){ + Vec4 color=ReadVec4(); + } + + for( int i=0;i::iterator it=_vertices.begin();it!=_vertices.end();++it ){ + it->index=-1; + } + + vector verts,tris; + + while( ChunkSize() ){ + int i=ReadInt(); + Vertex &vert=_vertices[i]; + if( vert.index==-1 ){ + vert.index=verts.size(); + verts.push_back( i ); + } + tris.push_back( vert.index ); + } + + if( verts.empty() || tris.empty() ) return; + + unsigned n_verts=verts.size(); + unsigned n_tris=tris.size()/3; + + //OK, we have a whole mesh... + aiVector3D *mv=new aiVector3D[n_verts]; + aiVector3D *mn=new aiVector3D[n_verts]; + aiVector3D *mc=new aiVector3D[n_verts]; + for( unsigned i=0;imMaterialIndex=matid; + + mesh->mNumVertices=n_verts; + mesh->mVertices=mv; + mesh->mNormals=mn; + mesh->mTextureCoords[0]=mc; + + mesh->mNumFaces=n_tris; + mesh->mFaces=faces; + + _meshes.push_back( mesh ); +} + +void B3DImporter::ReadMESH(){ + int matid=ReadInt(); + + _vertices.clear(); + + while( ChunkSize() ){ + string t=ReadChunk(); + if( t=="VRTS" ){ + ReadVRTS(); + }else if( t=="TRIS" ){ + ReadTRIS(); + } + ExitChunk(); + } + + _vertices.clear(); +} + +void B3DImporter::ReadNODE(){ + + string name=ReadString(); + Vec3 trans=ReadVec3(); + Vec3 scale=ReadVec3(); + Vec4 rot=ReadVec4(); + + while( ChunkSize() ){ + string t=ReadChunk(); + if( t=="MESH" ){ + ReadMESH(); + } + ExitChunk(); + } +} + +void B3DImporter::ReadBB3D(){ + string t=ReadChunk(); + if( t=="BB3D" ){ + int version=ReadInt(); + while( ChunkSize() ){ + string t=ReadChunk(); + if( t=="TEXS" ){ + ReadTEXS(); + }else if( t=="BRUS" ){ + ReadBRUS(); + }else if( t=="NODE" ){ + ReadNODE(); + } + ExitChunk(); + } + } + ExitChunk(); +} diff --git a/code/B3DImporter.h b/code/B3DImporter.h new file mode 100644 index 000000000..d43e186a7 --- /dev/null +++ b/code/B3DImporter.h @@ -0,0 +1,106 @@ + +/* +Open Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file Definition of the .b3d importer class. */ + +#ifndef AI_B3DIMPORTER_H_INC +#define AI_B3DIMPORTER_H_INC + +#include "../include/aiTypes.h" +#include "../include/aiMesh.h" +#include "../include/aiMaterial.h" + +#include +#include + +namespace Assimp{ + +class B3DImporter : public BaseImporter{ +public: + + virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const; + +protected: + + virtual void GetExtensionList(std::string& append); + virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); + +private: + + struct Vec2{ float x,y; }; + struct Vec3{ float x,y,z; }; + struct Vec4{ float x,y,z,w; }; + struct Texture{ std::string name; }; + struct Vertex{ int index;Vec3 position,normal,texcoords; }; + + int ReadByte(); + int ReadInt(); + float ReadFloat(); + Vec2 ReadVec2(); + Vec3 ReadVec3(); + Vec4 ReadVec4(); + std::string ReadString(); + std::string ReadChunk(); + void ExitChunk(); + unsigned ChunkSize(); + + void ReadTEXS(); + void ReadBRUS(); + void ReadVRTS(); + void ReadTRIS(); + void ReadMESH(); + void ReadNODE(); + void ReadBB3D(); + + unsigned _pos; + unsigned _size; + std::vector _buf; + std::vector _stack; + + std::vector _textures; + std::vector _materials; + std::vector _vertices; + std::vector _meshes; +}; + +} + +#endif diff --git a/code/IRRLoader.cpp b/code/IRRLoader.cpp index 68ccb079d..76d01fda8 100644 --- a/code/IRRLoader.cpp +++ b/code/IRRLoader.cpp @@ -130,6 +130,29 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene, break; } attach.push_back(AttachmentInfo(scene,rootOut)); + + // now combine the material we've loaded for this mesh + // with the real meshes we got from the file. As we + // don't execute any pp-steps on the file, the numbers + // should be equal. If they are not, we can impossibly + // do this ... + if (root->materials.size() != (unsigned int)scene->mNumMaterials) + { + DefaultLogger::get()->warn("IRR: Failed to match imported materials " + "with the materials found in the IRR scene file"); + + break; + } + for (unsigned int i = 0; i < scene->mNumMaterials;++i) + { + // delete the old material + delete scene->mMaterials[i]; + + std::pair& src = root->materials[i]; + scene->mMaterials[i] = src.first; + + // Process material flags (e.g. lightmapping) + } } break; diff --git a/code/IRRMeshLoader.cpp b/code/IRRMeshLoader.cpp index e6f39a8ca..882de0789 100644 --- a/code/IRRMeshLoader.cpp +++ b/code/IRRMeshLoader.cpp @@ -455,6 +455,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile, int textMeaning = 0; int vertexFormat = 0; // 0 = normal; 1 = 2 tcoords, 2 = tangents bool useColors = false; + bool needLightMap = false; // Parse the XML file while (reader->read()) @@ -752,7 +753,12 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile, mat->AddProperty(&curColors[0].a,1,AI_MATKEY_OPACITY); } - /* TODO: Add lightmapping support here */ + // store the material flags for later use + curMesh->mNumUVComponents[3] = curMatFlags; + if ( curMatFlags & AI_IRRMESH_MAT_lightmap ) + { + needLightMap = true; + } }} break; @@ -783,10 +789,22 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile, if (materials.empty()) throw new ImportErrorException("IRRMESH: Unable to read a mesh from this file"); + if(needLightMap) + { + // Compute light map UV coordinates +// ComputeLightMapUVCoordinates(meshes,materials); + } + // now generate the output scene pScene->mNumMeshes = (unsigned int)meshes.size(); pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; - ::memcpy(pScene->mMeshes,&meshes[0],sizeof(void*)*pScene->mNumMeshes); + for (unsigned int i = 0; i < pScene->mNumMeshes;++i) + { + pScene->mMeshes[i] = meshes[i]; + + // clean this value ... + pScene->mMeshes[i]->mNumUVComponents[3] = 0; + } pScene->mNumMaterials = (unsigned int)materials.size(); pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; diff --git a/code/Importer.cpp b/code/Importer.cpp index 754370fb6..513795095 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -126,6 +126,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_BUILD_NO_Q3D_IMPORTER # include "Q3DLoader.h" #endif +#ifndef AI_BUILD_NO_B3D_IMPORTER +# include "B3DImporter.h" +#endif // PostProcess-Steps @@ -180,14 +183,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_BUILD_NO_FINDDEGENERATES_PROCESS # include "FindDegenerates.h" #endif - -// NOTE: the preprocessor code has been moved to the header as -// we've also declared the DeterminePType process in it, which -// can't be removed. - -//#ifndef AI_BUILD_NO_SORTBYPTYPE_PROCESS +#ifndef AI_BUILD_NO_SORTBYPTYPE_PROCESS # include "SortByPTypeProcess.h" -//#endif +#endif using namespace Assimp; @@ -282,6 +280,9 @@ Importer::Importer() : #if (!defined AI_BUILD_NO_Q3D_IMPORTER) mImporter.push_back( new Q3DImporter()); #endif +#if (!defined AI_BUILD_NO_B3D_IMPORTER) + mImporter.push_back( new B3DImporter()); +#endif // add an instance of each post processing step here in the order // of sequence it is executed. steps that are added here are not validated - @@ -292,8 +293,6 @@ Importer::Importer() : mPostProcessingSteps.push_back( new ValidateDSProcess()); #endif - mPostProcessingSteps.push_back( new DeterminePTypeHelperProcess()); - #if (!defined AI_BUILD_NO_FINDDEGENERATES_PROCESS) mPostProcessingSteps.push_back( new FindDegeneratesProcess()); diff --git a/code/LWOLoader.cpp b/code/LWOLoader.cpp index bbec87891..32d06d8fc 100644 --- a/code/LWOLoader.cpp +++ b/code/LWOLoader.cpp @@ -143,6 +143,8 @@ void LWOImporter::InternReadFile( const std::string& pFile, // old lightwave file format (prior to v6) if (AI_LWO_FOURCC_LWOB == fileType) { + DefaultLogger::get()->info("LWO file format: LWOB (<= LightWave 5.5)"); + mIsLWO2 = false; this->LoadLWOBFile(); } @@ -150,6 +152,8 @@ void LWOImporter::InternReadFile( const std::string& pFile, // new lightwave format else if (AI_LWO_FOURCC_LWO2 == fileType) { + DefaultLogger::get()->info("LWO file format: LWO2 (>= LightWave 6)"); + mIsLWO2 = true; this->LoadLWO2File(); } @@ -307,7 +311,7 @@ void LWOImporter::InternReadFile( const std::string& pFile, aiVector3D*& pp = pvUV[w]; const aiVector2D& src = ((aiVector2D*)&layer.mUVChannels[vUVChannelIndices[w]].rawData[0])[idx]; pp->x = src.x; - pp->y = 1.f-src.y; // DX to OGL + pp->y = src.y; // DX to OGL pp++; } diff --git a/code/MD3Loader.cpp b/code/MD3Loader.cpp index ea75f709a..a12e557f8 100644 --- a/code/MD3Loader.cpp +++ b/code/MD3Loader.cpp @@ -297,14 +297,14 @@ void MD3Importer::InternReadFile( { // read vertices pcMesh->mVertices[iCurrent].x = pcVertices[ pcTriangles->INDEXES[c]].X*AI_MD3_XYZ_SCALE; - pcMesh->mVertices[iCurrent].y = pcVertices[ pcTriangles->INDEXES[c]].Y*-1.0f*AI_MD3_XYZ_SCALE; + pcMesh->mVertices[iCurrent].y = pcVertices[ pcTriangles->INDEXES[c]].Y*AI_MD3_XYZ_SCALE; pcMesh->mVertices[iCurrent].z = pcVertices[ pcTriangles->INDEXES[c]].Z*AI_MD3_XYZ_SCALE; // convert the normal vector to uncompressed float3 format LatLngNormalToVec3(pcVertices[pcTriangles->INDEXES[c]].NORMAL, (float*)&pcMesh->mNormals[iCurrent]); - pcMesh->mNormals[iCurrent].y *= -1.0f; + //pcMesh->mNormals[iCurrent].y *= -1.0f; // read texture coordinates pcMesh->mTextureCoords[0][iCurrent].x = pcUVs[ pcTriangles->INDEXES[c]].U; diff --git a/code/Q3DLoader.cpp b/code/Q3DLoader.cpp index 31c8bad8e..00793d317 100644 --- a/code/Q3DLoader.cpp +++ b/code/Q3DLoader.cpp @@ -562,11 +562,11 @@ outer: for (unsigned int i = 0; i < pScene->mNumMeshes;++i) pScene->mRootNode->mMeshes[i] = i; - pScene->mRootNode->mTransformation *= aiMatrix4x4( + /*pScene->mRootNode->mTransformation *= aiMatrix4x4( 1.f, 0.f, 0.f, 0.f, 0.f, -1.f,0.f, 0.f, 0.f, 0.f, 1.f, 0.f, - 0.f, 0.f, 0.f, 1.f); + 0.f, 0.f, 0.f, 1.f);*/ // Add cameras and light sources to the scene root node pScene->mRootNode->mNumChildren = pScene->mNumLights+pScene->mNumCameras; diff --git a/code/ScenePreprocessor.cpp b/code/ScenePreprocessor.cpp index a76ae53a9..2b09fb948 100644 --- a/code/ScenePreprocessor.cpp +++ b/code/ScenePreprocessor.cpp @@ -48,7 +48,10 @@ void ScenePreprocessor::ProcessScene (aiScene* _scene) { scene = _scene; - // - nothing to do for meshes for the moment + // Process all meshes + for (unsigned int i = 0; i < scene->mNumMeshes;++i) + ProcessMesh(scene->mMeshes[i]); + // - nothing to do for materials for the moment // - nothing to do for nodes for the moment // - nothing to do for textures for the moment @@ -60,6 +63,37 @@ void ScenePreprocessor::ProcessScene (aiScene* _scene) ProcessAnimation(scene->mAnimations[i]); } +// --------------------------------------------------------------------------- +void ScenePreprocessor::ProcessMesh (aiMesh* mesh) +{ + // If the information which primitive types are there in the + // mesh is currently not available, compute it. + if (!mesh->mPrimitiveTypes) + { + for (unsigned int a = 0; a < mesh->mNumFaces; ++a) + { + aiFace& face = mesh->mFaces[a]; + switch (face.mNumIndices) + { + case 3u: + mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; + break; + + case 2u: + mesh->mPrimitiveTypes |= aiPrimitiveType_LINE; + break; + + case 1u: + mesh->mPrimitiveTypes |= aiPrimitiveType_POINT; + break; + + default: + mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON; + break; + } + } + } +} // --------------------------------------------------------------------------- void ScenePreprocessor::ProcessAnimation (aiAnimation* anim) diff --git a/code/ScenePreprocessor.h b/code/ScenePreprocessor.h index 3fda5392a..202cd52a7 100644 --- a/code/ScenePreprocessor.h +++ b/code/ScenePreprocessor.h @@ -64,6 +64,7 @@ public: protected: void ProcessAnimation (aiAnimation* anim); + void ProcessMesh (aiMesh* mesh); protected: diff --git a/code/SortByPTypeProcess.cpp b/code/SortByPTypeProcess.cpp index c49095cf7..14358e307 100644 --- a/code/SortByPTypeProcess.cpp +++ b/code/SortByPTypeProcess.cpp @@ -51,64 +51,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -DeterminePTypeHelperProcess ::DeterminePTypeHelperProcess() -{ -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -DeterminePTypeHelperProcess::~DeterminePTypeHelperProcess() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool DeterminePTypeHelperProcess::IsActive( unsigned int pFlags) const -{ - // this step is always active - return true; -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void DeterminePTypeHelperProcess::Execute( aiScene* pScene) -{ - DefaultLogger::get()->debug("DeterminePTypeHelper begin"); - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - { - aiMesh* mesh = pScene->mMeshes[i]; - if (!mesh->mPrimitiveTypes) - { - for (unsigned int a = 0; a < mesh->mNumFaces; ++a) - { - aiFace& face = mesh->mFaces[a]; - switch (face.mNumIndices) - { - case 3u: - mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; - break; - - case 2u: - mesh->mPrimitiveTypes |= aiPrimitiveType_LINE; - break; - - case 1u: - mesh->mPrimitiveTypes |= aiPrimitiveType_POINT; - break; - - default: - mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON; - break; - } - } - } - } - DefaultLogger::get()->debug("DeterminePTypeHelper finished"); -} - // ------------------------------------------------------------------------------------------------ diff --git a/code/SortByPTypeProcess.h b/code/SortByPTypeProcess.h index dd48b4ed4..40073876e 100644 --- a/code/SortByPTypeProcess.h +++ b/code/SortByPTypeProcess.h @@ -50,35 +50,6 @@ class SortByPTypeProcessTest; namespace Assimp { -// --------------------------------------------------------------------------- -/** DeterminePTypeHelperProcess: If aiMesh::mPrimitiveTypes is 0, - * this step determines the types of primitive a mesh consists of. -*/ -class ASSIMP_API DeterminePTypeHelperProcess : public BaseProcess -{ - friend class Importer; - friend class ::SortByPTypeProcessTest; // grant the unit test full access to us - -protected: - /** Constructor to be privately used by Importer */ - DeterminePTypeHelperProcess(); - - /** Destructor, private as well */ - ~DeterminePTypeHelperProcess(); - -public: - // ------------------------------------------------------------------- - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - void Execute( aiScene* pScene); - -private: - -}; - -#if (!defined AI_BUILD_NO_SORTBYPTYPE_PROCESS) - // --------------------------------------------------------------------------- /** SortByPTypeProcess: Sorts meshes by the types of primitives they contain. * A mesh with 5 lines, 3 points and 145 triangles would be split in 3 @@ -111,7 +82,6 @@ private: int configRemoveMeshes; }; -#endif } // end of namespace Assimp diff --git a/code/makefile b/code/makefile index 6edadb7dc..50190d87c 100644 --- a/code/makefile +++ b/code/makefile @@ -72,7 +72,8 @@ SOURCES = AssimpPCH.cpp \ IRRMeshLoader.cpp \ IRRLoader.cpp \ Q3DLoader.cpp \ - ScenePreprocessor.cpp + ScenePreprocessor.cpp \ + B3DImporter.cpp OBJECTS = $(SOURCES:.cpp=.o) diff --git a/code/makefile.mingw b/code/makefile.mingw index 50df1e48d..ef72d619b 100644 --- a/code/makefile.mingw +++ b/code/makefile.mingw @@ -72,7 +72,9 @@ SOURCES = AssimpPCH.cpp \ IRRMeshLoader.cpp \ IRRLoader.cpp \ Q3DLoader.cpp \ - ScenePreprocessor.cpp + ScenePreprocessor.cpp \ + B3DImporter.cpp + OBJECTS = $(SOURCES:.cpp=.o) diff --git a/workspaces/vc8/assimp.vcproj b/workspaces/vc8/assimp.vcproj index a4a16774c..885c21bce 100644 --- a/workspaces/vc8/assimp.vcproj +++ b/workspaces/vc8/assimp.vcproj @@ -1402,6 +1402,18 @@ > + + + + + +