From 9f10553601e390243d9a163f092bc25708317cfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20B=C3=BCchler?= Date: Thu, 30 Jan 2014 02:39:04 +0100 Subject: [PATCH] Fix 3DS instances loading, fixes #151 --- code/3DSConverter.cpp | 74 +++++++++++++++++++++++++++---------------- code/3DSHelper.h | 7 ++++ code/3DSLoader.cpp | 16 +++++++--- 3 files changed, 66 insertions(+), 31 deletions(-) diff --git a/code/3DSConverter.cpp b/code/3DSConverter.cpp index 91ace96b5..8687e5e46 100644 --- a/code/3DSConverter.cpp +++ b/code/3DSConverter.cpp @@ -467,34 +467,41 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut, const unsigned int iIndex = iArray[i]; aiMesh* const mesh = pcSOut->mMeshes[iIndex]; - // Transform the vertices back into their local space - // fixme: consider computing normals after this, so we don't need to transform them - const aiVector3D* const pvEnd = mesh->mVertices+mesh->mNumVertices; - aiVector3D* pvCurrent = mesh->mVertices, *t2 = mesh->mNormals; - - for (;pvCurrent != pvEnd;++pvCurrent,++t2) { - *pvCurrent = mInv * (*pvCurrent); - *t2 = mInvTransposed * (*t2); - } - - // Handle negative transformation matrix determinant -> invert vertex x - if (imesh->mMat.Determinant() < 0.0f) + if (mesh->mColors[1] == NULL) { - /* we *must* have normals */ - for (pvCurrent = mesh->mVertices,t2 = mesh->mNormals;pvCurrent != pvEnd;++pvCurrent,++t2) { - pvCurrent->x *= -1.f; - t2->x *= -1.f; - } - DefaultLogger::get()->info("3DS: Flipping mesh X-Axis"); - } + // Transform the vertices back into their local space + // fixme: consider computing normals after this, so we don't need to transform them + const aiVector3D* const pvEnd = mesh->mVertices + mesh->mNumVertices; + aiVector3D* pvCurrent = mesh->mVertices, *t2 = mesh->mNormals; - // Handle pivot point - if(pivot.x || pivot.y || pivot.z) - { - for (pvCurrent = mesh->mVertices;pvCurrent != pvEnd;++pvCurrent) { - *pvCurrent -= pivot; + for (; pvCurrent != pvEnd; ++pvCurrent, ++t2) { + *pvCurrent = mInv * (*pvCurrent); + *t2 = mInvTransposed * (*t2); } + + // Handle negative transformation matrix determinant -> invert vertex x + if (imesh->mMat.Determinant() < 0.0f) + { + /* we *must* have normals */ + for (pvCurrent = mesh->mVertices, t2 = mesh->mNormals; pvCurrent != pvEnd; ++pvCurrent, ++t2) { + pvCurrent->x *= -1.f; + t2->x *= -1.f; + } + DefaultLogger::get()->info("3DS: Flipping mesh X-Axis"); + } + + // Handle pivot point + if (pivot.x || pivot.y || pivot.z) + { + for (pvCurrent = mesh->mVertices; pvCurrent != pvEnd; ++pvCurrent) { + *pvCurrent -= pivot; + } + } + + mesh->mColors[1] = (aiColor4D*)1; } + else + mesh->mColors[1] = (aiColor4D*)1; // Setup the mesh index pcOut->mMeshes[i] = iIndex; @@ -502,7 +509,17 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut, } // Setup the name of the node - pcOut->mName.Set(pcIn->mName); + // First instance keeps its name otherwise something might break, all others will be postfixed with their instance number + if (pcIn->mInstanceNumber > 1) + { + char tmp[12]; + ASSIMP_itoa10(tmp, pcIn->mInstanceNumber); + std::string tempStr = pcIn->mName + "_inst_"; + tempStr += tmp; + pcOut->mName.Set(tempStr); + } + else + pcOut->mName.Set(pcIn->mName); // Now build the transformation matrix of the node // ROTATION @@ -784,9 +801,12 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut) AddNodeToGraph(pcOut, pcOut->mRootNode, mRootNode,m); } - // We used the first vertex color set to store some emporary values so we need to cleanup here - for (unsigned int a = 0; a < pcOut->mNumMeshes;++a) + // We used the first and second vertex color set to store some temporary values so we need to cleanup here + for (unsigned int a = 0; a < pcOut->mNumMeshes; ++a) + { pcOut->mMeshes[a]->mColors[0] = NULL; + pcOut->mMeshes[a]->mColors[1] = NULL; + } pcOut->mRootNode->mTransformation = aiMatrix4x4( 1.f,0.f,0.f,0.f, diff --git a/code/3DSHelper.h b/code/3DSHelper.h index 115f396e9..adf1a2ff4 100644 --- a/code/3DSHelper.h +++ b/code/3DSHelper.h @@ -481,6 +481,7 @@ struct Node : mHierarchyPos (0) , mHierarchyIndex (0) + , mInstanceCount (1) { static int iCnt = 0; @@ -510,6 +511,9 @@ struct Node //! Name of the node std::string mName; + //! InstanceNumber of the node + int32_t mInstanceNumber; + //! Dummy nodes: real name to be combined with the $$$DUMMY std::string mDummyName; @@ -539,6 +543,9 @@ struct Node //! Pivot position loaded from the file aiVector3D vPivot; + //instance count, will be kept only for the first node + int32_t mInstanceCount; + //! Add a child node, setup the right parent node for it //! \param pc Node to be 'adopted' inline Node& push_back(Node* pc) diff --git a/code/3DSLoader.cpp b/code/3DSLoader.cpp index f16f3a27d..4f5614a00 100644 --- a/code/3DSLoader.cpp +++ b/code/3DSLoader.cpp @@ -659,14 +659,22 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) // Now find out whether we have this node already (target animation channels // are stored with a separate object ID) D3DS::Node* pcNode = FindNode(mRootNode,name); - if (pcNode) + int instanceNumber = 1; + + if ( pcNode) { - // Make this node the current node - mCurrentNode = pcNode; - break; + // if the source is not a CHUNK_TRACKINFO block it wont be an object instance + if (parent != Discreet3DS::CHUNK_TRACKINFO) + { + mCurrentNode = pcNode; + break; + } + pcNode->mInstanceCount++; + instanceNumber = pcNode->mInstanceCount; } pcNode = new D3DS::Node(); pcNode->mName = name; + pcNode->mInstanceNumber = instanceNumber; // There are two unknown values which we can safely ignore stream->IncPtr(4);