Переглянути джерело

Merge remote-tracking branch 'official/master' into contrib

Léo Terziman 11 роки тому
батько
коміт
8fad549649

+ 4 - 1
CREDITS

@@ -141,4 +141,7 @@ Bugfix for a compiler fix for iOS on arm.
 Rewrite of PyAssimp, distutils and Python3 support
 Rewrite of PyAssimp, distutils and Python3 support
 
 
 - albert-wang
 - albert-wang
-Bugfixes for the collada parser
+Bugfixes for the collada parser
+
+- Ya ping Jin
+Bugfixes for uv-tanget calculation.

+ 46 - 26
code/3DSConverter.cpp

@@ -467,34 +467,41 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,
 			const unsigned int iIndex = iArray[i];
 			const unsigned int iIndex = iArray[i];
 			aiMesh* const mesh = pcSOut->mMeshes[iIndex];
 			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;
+				// 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);
 				}
 				}
-				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;	
+				// 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
 			// Setup the mesh index
 			pcOut->mMeshes[i] = iIndex;
 			pcOut->mMeshes[i] = iIndex;
@@ -502,7 +509,17 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,
 	}
 	}
 
 
 	// Setup the name of the node
 	// 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
 	// Now build the transformation matrix of the node
 	// ROTATION
 	// ROTATION
@@ -784,9 +801,12 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut)
 		AddNodeToGraph(pcOut,  pcOut->mRootNode, mRootNode,m);
 		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[0] = NULL;
+		pcOut->mMeshes[a]->mColors[1] = NULL;
+	}
 
 
 	pcOut->mRootNode->mTransformation = aiMatrix4x4(
 	pcOut->mRootNode->mTransformation = aiMatrix4x4(
 		1.f,0.f,0.f,0.f,
 		1.f,0.f,0.f,0.f,

+ 7 - 0
code/3DSHelper.h

@@ -481,6 +481,7 @@ struct Node
 
 
 		:	mHierarchyPos		(0)
 		:	mHierarchyPos		(0)
 		,	mHierarchyIndex		(0)
 		,	mHierarchyIndex		(0)
+		,	mInstanceCount		(1)
 
 
 	{
 	{
 		static int iCnt = 0;
 		static int iCnt = 0;
@@ -510,6 +511,9 @@ struct Node
 	//! Name of the node
 	//! Name of the node
 	std::string mName;
 	std::string mName;
 
 
+	//! InstanceNumber of the node
+	int32_t mInstanceNumber;
+
 	//! Dummy nodes: real name to be combined with the $$$DUMMY 
 	//! Dummy nodes: real name to be combined with the $$$DUMMY 
 	std::string mDummyName;
 	std::string mDummyName;
 
 
@@ -539,6 +543,9 @@ struct Node
 	//! Pivot position loaded from the file
 	//! Pivot position loaded from the file
 	aiVector3D vPivot;
 	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
 	//! Add a child node, setup the right parent node for it
 	//! \param pc Node to be 'adopted'
 	//! \param pc Node to be 'adopted'
 	inline Node& push_back(Node* pc)
 	inline Node& push_back(Node* pc)

+ 12 - 4
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 
 		// Now find out whether we have this node already (target animation channels 
 		// are stored with a separate object ID)
 		// are stored with a separate object ID)
 		D3DS::Node* pcNode = FindNode(mRootNode,name);
 		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 = new D3DS::Node();
 		pcNode->mName = name;
 		pcNode->mName = name;
+		pcNode->mInstanceNumber = instanceNumber;
 
 
 		// There are two unknown values which we can safely ignore
 		// There are two unknown values which we can safely ignore
 		stream->IncPtr(4);
 		stream->IncPtr(4);

+ 5 - 0
code/CMakeLists.txt

@@ -711,6 +711,11 @@ SET_TARGET_PROPERTIES( assimp PROPERTIES
 	SOVERSION ${ASSIMP_SOVERSION} # use full version 
 	SOVERSION ${ASSIMP_SOVERSION} # use full version 
     OUTPUT_NAME assimp${ASSIMP_LIBRARY_SUFFIX}
     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
 # Build against external unzip, or add ../contrib/unzip so
 # assimp can #include "unzip.h"
 # assimp can #include "unzip.h"
 if (UNZIP_FOUND)
 if (UNZIP_FOUND)

+ 40 - 14
code/CalcTangentsProcess.cpp

@@ -55,8 +55,9 @@ using namespace Assimp;
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 // Constructor to be privately used by Importer
 CalcTangentsProcess::CalcTangentsProcess()
 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.
 // Executes the post processing step on the given imported data.
 void CalcTangentsProcess::SetupProperties(const Importer* pImp)
 void CalcTangentsProcess::SetupProperties(const Importer* pImp)
 {
 {
+    ai_assert( NULL != pImp );
+
 	// get the current value of the property
 	// get the current value of the property
 	configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE,45.f);
 	configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE,45.f);
 	configMaxAngle = std::max(std::min(configMaxAngle,45.0f),0.0f);
 	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.
 // Executes the post processing step on the given imported data.
 void CalcTangentsProcess::Execute( aiScene* pScene)
 void CalcTangentsProcess::Execute( aiScene* pScene)
 {
 {
-	DefaultLogger::get()->debug("CalcTangentsProcess begin");
+    ai_assert( NULL != pScene );
+
+    DefaultLogger::get()->debug("CalcTangentsProcess begin");
 
 
 	bool bHas = false;
 	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(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 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 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;
 		float dirCorrection = (tx * sy - ty * sx) < 0.0f ? -1.0f : 1.0f;
-
-		// 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
+        // 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 coord's would point in model space
+		// bitangent's points along the positive Y axis of the texture coord's, respectively
 		aiVector3D tangent, bitangent;
 		aiVector3D tangent, bitangent;
 		tangent.x = (w.x * sy - v.x * ty) * dirCorrection;
 		tangent.x = (w.x * sy - v.x * ty) * dirCorrection;
         tangent.y = (w.y * sy - v.y * 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;
         bitangent.z = (w.z * sx - v.z * tx) * dirCorrection;
 
 
 		// store for every vertex of that face
 		// 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];
 			unsigned int p = face.mIndices[b];
 
 
 			// project tangent and bitangent into the plane formed by the vertex' normal
 			// 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]);
 			aiVector3D localBitangent = bitangent - meshNorm[p] * (bitangent * meshNorm[p]);
 			localTangent.Normalize(); localBitangent.Normalize();
 			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;
 		}
 		}
     }
     }
 
 

+ 1 - 1
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");
 	DefaultLogger::get()->error("Mapping type currently not implemented");
 }
 }