diff --git a/CREDITS b/CREDITS index 6fee05163..f75f0ff29 100644 --- a/CREDITS +++ b/CREDITS @@ -141,4 +141,7 @@ Bugfix for a compiler fix for iOS on arm. Rewrite of PyAssimp, distutils and Python3 support - albert-wang -Bugfixes for the collada parser \ No newline at end of file +Bugfixes for the collada parser + +- Ya ping Jin +Bugfixes for uv-tanget calculation. \ No newline at end of file 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); diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 187e7402d..8705429c2 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -711,6 +711,11 @@ SET_TARGET_PROPERTIES( assimp PROPERTIES SOVERSION ${ASSIMP_SOVERSION} # use full version OUTPUT_NAME assimp${ASSIMP_LIBRARY_SUFFIX} ) + +if (APPLE) + SET_TARGET_PROPERTIES( assimp PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}") +endif() + # Build against external unzip, or add ../contrib/unzip so # assimp can #include "unzip.h" if (UNZIP_FOUND) diff --git a/code/CalcTangentsProcess.cpp b/code/CalcTangentsProcess.cpp index 105de040a..46ab8f868 100644 --- a/code/CalcTangentsProcess.cpp +++ b/code/CalcTangentsProcess.cpp @@ -55,8 +55,9 @@ using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer CalcTangentsProcess::CalcTangentsProcess() -{ - this->configMaxAngle = AI_DEG_TO_RAD(45.f); +: configMaxAngle( AI_DEG_TO_RAD(45.f) ) +, configSourceUV( 0 ) { + // nothing to do here } // ------------------------------------------------------------------------------------------------ @@ -77,6 +78,8 @@ bool CalcTangentsProcess::IsActive( unsigned int pFlags) const // Executes the post processing step on the given imported data. void CalcTangentsProcess::SetupProperties(const Importer* pImp) { + ai_assert( NULL != pImp ); + // get the current value of the property configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE,45.f); configMaxAngle = std::max(std::min(configMaxAngle,45.0f),0.0f); @@ -89,14 +92,20 @@ void CalcTangentsProcess::SetupProperties(const Importer* pImp) // Executes the post processing step on the given imported data. void CalcTangentsProcess::Execute( aiScene* pScene) { - DefaultLogger::get()->debug("CalcTangentsProcess begin"); + ai_assert( NULL != pScene ); + + DefaultLogger::get()->debug("CalcTangentsProcess begin"); bool bHas = false; - for( unsigned int a = 0; a < pScene->mNumMeshes; a++) + for ( unsigned int a = 0; a < pScene->mNumMeshes; a++ ) { if(ProcessMesh( pScene->mMeshes[a],a))bHas = true; + } - if (bHas)DefaultLogger::get()->info("CalcTangentsProcess finished. Tangents have been calculated"); - else DefaultLogger::get()->debug("CalcTangentsProcess finished"); + if ( bHas ) { + DefaultLogger::get()->info("CalcTangentsProcess finished. Tangents have been calculated"); + } else { + DefaultLogger::get()->debug("CalcTangentsProcess finished"); + } } // ------------------------------------------------------------------------------------------------ @@ -179,9 +188,14 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) float sx = meshTex[p1].x - meshTex[p0].x, sy = meshTex[p1].y - meshTex[p0].y; float tx = meshTex[p2].x - meshTex[p0].x, ty = meshTex[p2].y - meshTex[p0].y; float dirCorrection = (tx * sy - ty * sx) < 0.0f ? -1.0f : 1.0f; + // when t1, t2, t3 in same position in UV space, just use default UV direction. + if ( 0 == sx && 0 ==sy && 0 == tx && 0 == ty ) { + sx = 0.0; sy = 1.0; + tx = 1.0; ty = 0.0; + } - // tangent points in the direction where to positive X axis of the texture coords would point in model space - // bitangents points along the positive Y axis of the texture coords, respectively + // tangent points in the direction where to positive X axis of the texture coord's would point in model space + // bitangent's points along the positive Y axis of the texture coord's, respectively aiVector3D tangent, bitangent; tangent.x = (w.x * sy - v.x * ty) * dirCorrection; tangent.y = (w.y * sy - v.y * ty) * dirCorrection; @@ -191,8 +205,7 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) bitangent.z = (w.z * sx - v.z * tx) * dirCorrection; // store for every vertex of that face - for( unsigned int b = 0; b < face.mNumIndices; b++) - { + for( unsigned int b = 0; b < face.mNumIndices; ++b ) { unsigned int p = face.mIndices[b]; // project tangent and bitangent into the plane formed by the vertex' normal @@ -200,9 +213,22 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) aiVector3D localBitangent = bitangent - meshNorm[p] * (bitangent * meshNorm[p]); localTangent.Normalize(); localBitangent.Normalize(); - // and write it into the mesh. - meshTang[p] = localTangent; - meshBitang[p] = localBitangent; + // reconstruct tangent/bitangent according to normal and bitangent/tangent when it's infinite or NaN. + bool invalid_tangent = is_special_float(localTangent.x) || is_special_float(localTangent.y) || is_special_float(localTangent.z); + bool invalid_bitangent = is_special_float(localBitangent.x) || is_special_float(localBitangent.y) || is_special_float(localBitangent.z); + if (invalid_tangent != invalid_bitangent) { + if (invalid_tangent) { + localTangent = meshNorm[p] ^ localBitangent; + localTangent.Normalize(); + } else { + localBitangent = localTangent ^ meshNorm[p]; + localBitangent.Normalize(); + } + } + + // and write it into the mesh. + meshTang[ p ] = localTangent; + meshBitang[ p ] = localBitangent; } } diff --git a/code/ComputeUVMappingProcess.cpp b/code/ComputeUVMappingProcess.cpp index a5ff944e3..671371bb5 100644 --- a/code/ComputeUVMappingProcess.cpp +++ b/code/ComputeUVMappingProcess.cpp @@ -380,7 +380,7 @@ void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D& } // ------------------------------------------------------------------------------------------------ -void ComputeUVMappingProcess::ComputeBoxMapping(aiMesh* /*mesh*/, aiVector3D* /*out*/) +void ComputeUVMappingProcess::ComputeBoxMapping( aiMesh*, aiVector3D* ) { DefaultLogger::get()->error("Mapping type currently not implemented"); }