浏览代码

Integrate MikkTSpace calculation for tangents

Kim Kulling 1 月之前
父节点
当前提交
5081d263db

+ 8 - 4
code/PostProcessing/CalcTangentsProcess.cpp

@@ -3,9 +3,7 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2022, assimp team
-
-
+Copyright (c) 2006-2025, assimp team
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -63,7 +61,11 @@ CalcTangentsProcess::CalcTangentsProcess() :
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the processing step is present in the given flag field.
 // Returns whether the processing step is present in the given flag field.
 bool CalcTangentsProcess::IsActive(unsigned int pFlags) const {
 bool CalcTangentsProcess::IsActive(unsigned int pFlags) const {
-    return (pFlags & aiProcess_CalcTangentSpace) != 0;
+    const bool active = ((pFlags & aiProcess_CalcTangentSpace) != 0);
+    if (mActive) {
+        return active;
+    }
+    return false;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -71,6 +73,8 @@ bool CalcTangentsProcess::IsActive(unsigned int pFlags) const {
 void CalcTangentsProcess::SetupProperties(const Importer *pImp) {
 void CalcTangentsProcess::SetupProperties(const Importer *pImp) {
     ai_assert(nullptr != pImp);
     ai_assert(nullptr != pImp);
 
 
+    mActive = pImp->GetPropertyBool(AI_CONFIG_POSTPROCESS_USE_MIKKTSPACE_TANGENTS, false);
+
     // 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);

+ 1 - 0
code/PostProcessing/CalcTangentsProcess.h

@@ -103,6 +103,7 @@ private:
     /** Configuration option: maximum smoothing angle, in radians*/
     /** Configuration option: maximum smoothing angle, in radians*/
     float configMaxAngle;
     float configMaxAngle;
     unsigned int configSourceUV;
     unsigned int configSourceUV;
+    bool mActive = true;
 };
 };
 
 
 } // end of namespace Assimp
 } // end of namespace Assimp

+ 88 - 1
code/PostProcessing/GenerateMikkTSpaceTangents.cpp

@@ -1,13 +1,100 @@
 #include "GenerateMikkTSpaceTangents.h"
 #include "GenerateMikkTSpaceTangents.h"
+#include <assimp/scene.h>
+#include <assimp/postprocess.h>
 
 
 namespace Assimp {
 namespace Assimp {
 
 
-bool GenerateMikkTSpaceTangents::IsActive(unsigned int pFlags) const {
+static int get_vertex_index(const SMikkTSpaceContext *context, int iFace, int iVert);
+static int get_num_faces(const SMikkTSpaceContext *context);
+static int get_num_vertices_of_face(const SMikkTSpaceContext *context, int iFace);
+static void get_position(const SMikkTSpaceContext *context, float outpos[], int iFace, int iVert);
+static void get_normal(const SMikkTSpaceContext *context, float outnormal[], int iFace, int iVert);
+static void get_tex_coords(const SMikkTSpaceContext *context, float outuv[], int iFace, int iVert);
+static void set_tspace_basic(const SMikkTSpaceContext *context, const float tangentu[], float fSign, int iFace, int iVert);
+
+static int get_num_faces(const SMikkTSpaceContext *context) {
+    aiMesh *currentMesh = static_cast<aiMesh*>(context->m_pUserData);
+    const int numFaces = static_cast<int>(currentMesh->mNumFaces);
+
+    return numFaces;
+}
+
+static int get_num_vertices_of_face(const SMikkTSpaceContext *context, int iFace) {
+    aiMesh *currentMesh = static_cast<aiMesh*>(context->m_pUserData);
+    const aiFace &face = currentMesh->mFaces[iFace];
+    return face.mNumIndices;
+}
+
+static void get_position(const SMikkTSpaceContext *context, float outpos[], int iFace, int iVert) {
+    aiMesh *currentMesh = static_cast<aiMesh*>(context->m_pUserData);
+    const aiVector3D &v = currentMesh->mVertices[static_cast<size_t>(iVert)];
+    outpos[0] = v.x;
+    outpos[1] = v.y;
+    outpos[2] = v.z;
+}
+
+static void get_normal(const SMikkTSpaceContext *context, float outnormal[], int iFace, int iVert) {
+    aiMesh *currentMesh = static_cast<aiMesh*>(context->m_pUserData);
+    const aiVector3D &n = currentMesh->mNormals[static_cast<size_t>(iVert)];
+    outnormal[0] = n.x;
+    outnormal[0] = n.y;
+    outnormal[0] = n.z;
+}
 
 
+static void get_tex_coords(const SMikkTSpaceContext *context, float outuv[], int iFace, int iVert) {
+    aiMesh *currentMesh = static_cast<aiMesh*>(context->m_pUserData);
+    aiVector3D &t = currentMesh->mTextureCoords[static_cast<size_t>(iVert)][0];
+    if (currentMesh->mNumUVComponents[iVert] == 2) {
+        outuv[0] = t.x;
+        outuv[1] = t.y;
+    } else if (currentMesh->mNumUVComponents[iVert] == 3){
+        outuv[0] = t.x;
+        outuv[1] = t.y;
+        outuv[2] = t.z;
+    }
+}
+
+static void set_tspace_basic(const SMikkTSpaceContext *context, const float tangentu[], float fSign, int iFace, int iVert) {
+    aiMesh *currentMesh = static_cast<aiMesh*>(context->m_pUserData);
+    currentMesh->mTangents[iVert].x = tangentu[0];
+    currentMesh->mTangents[iVert].y = tangentu[1];
+    currentMesh->mTangents[iVert].z = tangentu[1];
+}
+
+bool GenerateMikkTSpaceTangents::IsActive(unsigned int pFlags) const {
+    const bool active = ((pFlags & aiProcess_CalcTangentSpace) != 0);
+    if (mActive) {
+        return active;
+    }
+    return false;
 }
 }
 
 
 void GenerateMikkTSpaceTangents::Execute(aiScene* pScene) {
 void GenerateMikkTSpaceTangents::Execute(aiScene* pScene) {
+    mIface.m_getNumFaces = get_num_faces;
+    mIface.m_getNumVerticesOfFace = get_num_vertices_of_face;
+    mIface.m_getNormal = get_normal;
+    mIface.m_getPosition = get_position;
+    mIface.m_getTexCoord = get_tex_coords;
+    mIface.m_setTSpaceBasic = set_tspace_basic;
+    mContext.m_pInterface = &mIface;
 
 
+    for (size_t i=0; i<pScene->mNumMeshes; ++i) {
+        aiMesh *mesh = pScene->mMeshes[i];
+        ExecutePerMesh(mesh);
+    }
 }
 }
 
 
+void GenerateMikkTSpaceTangents::SetupProperties(const Importer *pImp) {
+    mActive = pImp->GetPropertyBool(AI_CONFIG_POSTPROCESS_USE_MIKKTSPACE_TANGENTS, false);
 }
 }
+
+void GenerateMikkTSpaceTangents::ExecutePerMesh(aiMesh *mesh) {
+    if (mesh == nullptr) {
+        return;
+    }
+
+    mContext.m_pUserData = mesh;
+    genTangSpaceDefault(&mContext);
+}
+
+} // namespace Assimp

+ 7 - 3
code/PostProcessing/GenerateMikkTSpaceTangents.h

@@ -1,17 +1,21 @@
 #pragma once
 #pragma once
 
 
 #include "Common/BaseProcess.h"
 #include "Common/BaseProcess.h"
+#include "contrib/MikkTSpace/mikktspace.h"
 
 
 namespace Assimp {
 namespace Assimp {
 
 
-class GenerateMikkTSpaceTangents : public BaseProcess {
+class GenerateMikkTSpaceTangents final : public BaseProcess {
 public:
 public:
     GenerateMikkTSpaceTangents() = default;
     GenerateMikkTSpaceTangents() = default;
     ~GenerateMikkTSpaceTangents() override = default;
     ~GenerateMikkTSpaceTangents() override = default;
     bool IsActive(unsigned int pFlags) const override;
     bool IsActive(unsigned int pFlags) const override;
     void Execute(aiScene* pScene) override;
     void Execute(aiScene* pScene) override;
+    void ExecutePerMesh(aiMesh *mesh);
 
 
+private:
+    SMikkTSpaceInterface mIface;
+    SMikkTSpaceContext mContext;
 };
 };
 
 
-}
-
+} // namespace Assimp

+ 4 - 1
include/assimp/config.h.in

@@ -1131,6 +1131,9 @@ enum aiComponent
 #endif // AI_CONFIG_APP_SCALE_KEY
 #endif // AI_CONFIG_APP_SCALE_KEY
 
 
 
 
+#define AI_CONFIG_POSTPROCESS_USE_MIKKTSPACE_TANGENTS \
+        "POSTPROCESS_USE_MIKKTSPACE_TANGENTS"
+
 // ---------- All the Build/Compile-time defines ------------
 // ---------- All the Build/Compile-time defines ------------
 
 
 /** @brief Specifies if double precision is supported inside assimp
 /** @brief Specifies if double precision is supported inside assimp
@@ -1138,6 +1141,6 @@ enum aiComponent
  * Property type: Bool. Default value: undefined.
  * Property type: Bool. Default value: undefined.
  */
  */
 
 
-#cmakedefine ASSIMP_DOUBLE_PRECISION 1
+#define ASSIMP_DOUBLE_PRECISION 1
 
 
 #endif // !! AI_CONFIG_H_INC
 #endif // !! AI_CONFIG_H_INC

+ 0 - 1
include/assimp/mesh.h

@@ -1171,4 +1171,3 @@ struct aiSkeleton {
 #endif //! extern "C"
 #endif //! extern "C"
 
 
 #endif // AI_MESH_H_INC
 #endif // AI_MESH_H_INC
-