瀏覽代碼

bugfix:
add handling for special cases for the uv-calculation:
- When 3 vector have same UV, using default UV direction:
- When 2 vector have same UV, recalculate tangent/bitangent according to normal and bitangent/tangent.

Thanks to Ya ping Jin.

Signed-off-by: Kim Kulling <[email protected]>

Kim Kulling 11 年之前
父節點
當前提交
ec2b8dd3fa
共有 3 個文件被更改,包括 45 次插入16 次删除
  1. 4 1
      CREDITS
  2. 40 14
      code/CalcTangentsProcess.cpp
  3. 1 1
      code/ComputeUVMappingProcess.cpp

+ 4 - 1
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
+Bugfixes for the collada parser
+
+- Ya ping Jin
+Bugfixes for uv-tanget calculation.

+ 40 - 14
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;
-
-		// 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;
 		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;
 		}
     }
 

+ 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");
 }