Browse Source

Adds conversion functions and changes implementation of getTransform().

OTHGMars 6 years ago
parent
commit
1a7e6699c9
2 changed files with 104 additions and 60 deletions
  1. 86 57
      Engine/source/ts/assimp/assimpAppNode.cpp
  2. 18 3
      Engine/source/ts/assimp/assimpAppNode.h

+ 86 - 57
Engine/source/ts/assimp/assimpAppNode.cpp

@@ -32,6 +32,9 @@
 #include <assimp/types.h>
 
 AssimpAppNode::AssimpAppNode(const struct aiScene* scene, const struct aiNode* node, AssimpAppNode* parent)
+:  mInvertMeshes(false),
+   mLastTransformTime(TSShapeLoader::DefaultTime - 1),
+   mDefaultTransformValid(false)
 {
    mScene = scene;
    mNode = node;
@@ -45,7 +48,8 @@ AssimpAppNode::AssimpAppNode(const struct aiScene* scene, const struct aiNode* n
    }
 
    mParentName = dStrdup(parent ? parent->getName() : "ROOT");
-   Con::printf("[ASSIMP] Node Created: %s", mName);
+   assimpToTorqueMat(node->mTransformation, mNodeTransform);
+   Con::printf("[ASSIMP] Node Created: %s, Parent: %s", mName, mParentName);
 }
 
 // Get all child nodes
@@ -73,75 +77,100 @@ void AssimpAppNode::buildMeshList()
 
 MatrixF AssimpAppNode::getTransform(F32 time)
 {
-   // Translate from assimp matrix to torque matrix.
-   // They're both row major, I wish I could just cast
-   // but that doesn't seem to be an option.
+   // Check if we can use the last computed transform
+   if (time == mLastTransformTime)
+      return mLastTransform;
 
-   // Note: this should be cached, it doesn't change
-   //       at this level. This is base transform.
+   if (appParent) {
+      // Get parent node's transform
+      mLastTransform = appParent->getTransform(time);
+   }
+   else {
+      // no parent (ie. root level) => scale by global shape <unit>
+      mLastTransform.identity();
+      if (!isBounds())
+         convertMat(mLastTransform);
+
+      //mLastTransform.scale(ColladaUtils::getOptions().unit);
+   }
 
-   // Y and Z and optionally swapped.
+   mLastTransform.mul(mNodeTransform);
+   mLastTransformTime = time;
 
-   MatrixF mat(false);
-   mat.setRow(0, Point4F((F32)mNode->mTransformation.a1,
-       (F32)mNode->mTransformation.a3,
-       (F32)mNode->mTransformation.a2,
-       (F32)mNode->mTransformation.a4)
-   );
+   return mLastTransform;
+}
 
-   // Check for Y Z Swap
-   if ( Con::getBoolVariable("$Assimp::SwapYZ", false) )
+bool AssimpAppNode::animatesTransform(const AppSequence* appSeq)
+{
+   return false;
+}
+
+/// Get the world transform of the node at the specified time
+MatrixF AssimpAppNode::getNodeTransform(F32 time)
+{
+   // Avoid re-computing the default transform if possible
+   if (mDefaultTransformValid && time == TSShapeLoader::DefaultTime)
    {
-      mat.setRow(1, Point4F((F32)mNode->mTransformation.c1,
-          (F32)mNode->mTransformation.c3,
-          (F32)mNode->mTransformation.c2,
-          (F32)mNode->mTransformation.c4)
-      );
-      mat.setRow(2, Point4F((F32)mNode->mTransformation.b1,
-          (F32)mNode->mTransformation.b3,
-          (F32)mNode->mTransformation.b2,
-          (F32)mNode->mTransformation.b4)
-      );
-   } 
-   else 
+      return mDefaultNodeTransform;
+   }
+   else
    {
-      mat.setRow(1, Point4F((F32)mNode->mTransformation.b1,
-          (F32)mNode->mTransformation.b3,
-          (F32)mNode->mTransformation.b2,
-          (F32)mNode->mTransformation.b4)
-      );
-      mat.setRow(2, Point4F((F32)mNode->mTransformation.c1,
-          (F32)mNode->mTransformation.c3,
-          (F32)mNode->mTransformation.c2,
-          (F32)mNode->mTransformation.c4)
-      );
+      MatrixF nodeTransform = getTransform(time);
+
+      // Check for inverted node coordinate spaces => can happen when modelers
+      // use the 'mirror' tool in their 3d app. Shows up as negative <scale>
+      // transforms in the collada model.
+      if (m_matF_determinant(nodeTransform) < 0.0f)
+      {
+         // Mark this node as inverted so we can mirror mesh geometry, then
+         // de-invert the transform matrix
+         mInvertMeshes = true;
+         nodeTransform.scale(Point3F(1, 1, -1));
+      }
+
+      // Cache the default transform
+      if (time == TSShapeLoader::DefaultTime)
+      {
+         mDefaultTransformValid = true;
+         mDefaultNodeTransform = nodeTransform;
+      }
+
+      return nodeTransform;
    }
+}
+
+void AssimpAppNode::assimpToTorqueMat(const aiMatrix4x4& inAssimpMat, MatrixF& outMat)
+{
+   outMat.setRow(0, Point4F((F32)inAssimpMat.a1, (F32)inAssimpMat.a2,
+      (F32)inAssimpMat.a3, (F32)inAssimpMat.a4));
 
-   mat.setRow(3, Point4F((F32)mNode->mTransformation.d1,
-       (F32)mNode->mTransformation.d3,
-       (F32)mNode->mTransformation.d2,
-       (F32)mNode->mTransformation.d4)
-   );
+   outMat.setRow(1, Point4F((F32)inAssimpMat.b1, (F32)inAssimpMat.b2,
+      (F32)inAssimpMat.b3, (F32)inAssimpMat.b4));
 
-   // Node transformations are carried down the hiearchy
-   // so we need all of our parents transforms to make 
-   // this work.
-   /*if ( appParent != 0 )
-   {
-      MatrixF parentMat = appParent->getNodeTransform(time);
-      mat.mul(parentMat);
-   }*/
+   outMat.setRow(2, Point4F((F32)inAssimpMat.c1, (F32)inAssimpMat.c2,
+      (F32)inAssimpMat.c3, (F32)inAssimpMat.c4));
 
-   return mat;
+   outMat.setRow(3, Point4F((F32)inAssimpMat.d1, (F32)inAssimpMat.d2,
+      (F32)inAssimpMat.d3, (F32)inAssimpMat.d4));
 }
 
-bool AssimpAppNode::animatesTransform(const AppSequence* appSeq)
+void AssimpAppNode::convertMat(MatrixF& outMat)
 {
-   return false;
+   if (Con::getBoolVariable("$Assimp::SwapYZ", false))
+   {
+      MatrixF rotMat(EulerF(-M_HALFPI_F, 0, 0));
+      Point3F pos = outMat.getPosition();
+      outMat.mulL(rotMat);
+      rotMat.mulP(pos);
+      outMat.setPosition(pos);
+   }
 }
 
-/// Get the world transform of the node at the specified time
-MatrixF AssimpAppNode::getNodeTransform(F32 time)
+void AssimpAppNode::convertPoint(Point3F& outPoint)
 {
-   return getTransform(time);
-}
+   if (Con::getBoolVariable("$Assimp::SwapYZ", false))
+   {
+      MatrixF rotMat(EulerF(-M_HALFPI_F, 0, 0));
+      rotMat.mulP(outPoint);
+   }
+}

+ 18 - 3
Engine/source/ts/assimp/assimpAppNode.h

@@ -33,6 +33,10 @@
 #include "ts/collada/colladaExtensions.h"
 #endif
 
+#ifndef AI_TYPES_H_INC
+#include <assimp/types.h>
+#endif
+
 class AssimpAppNode : public AppNode
 {
    typedef AppNode Parent;
@@ -44,9 +48,16 @@ class AssimpAppNode : public AppNode
 
 protected:
 
-   const struct aiScene*      mScene;
-   const struct aiNode*       mNode;        ///< Pointer to the node in the Collada DOM
-   AssimpAppNode*             appParent;        ///< Parent node in Collada-space
+   const struct aiScene*   mScene;
+   const struct aiNode*    mNode;                  ///< Pointer to the assimp scene node
+   AssimpAppNode*          appParent;              ///< Parent node
+   MatrixF                 mNodeTransform;         ///< Scene node transform converted to TorqueSpace (filled for ALL nodes)
+
+   bool                    mInvertMeshes;          ///< True if this node's coordinate space is inverted (left handed)
+   F32                     mLastTransformTime;     ///< Time of the last transform lookup (getTransform)
+   MatrixF                 mLastTransform;         ///< Last transform lookup (getTransform) (Only Non-Dummy Nodes)
+   bool                    mDefaultTransformValid; ///< Flag indicating whether the defaultNodeTransform is valid
+   MatrixF                 mDefaultNodeTransform;  ///< Transform at DefaultTime (Only Non-Dummy Nodes)
 
 public:
 
@@ -93,6 +104,10 @@ public:
    MatrixF getNodeTransform(F32 time);
    bool animatesTransform(const AppSequence* appSeq);
    bool isParentRoot() { return (appParent == NULL); }
+
+   static void assimpToTorqueMat(const aiMatrix4x4& inAssimpMat, MatrixF& outMat);
+   static void convertMat(MatrixF& outMat);
+   static void convertPoint(Point3F& outPoint);
 };
 
 #endif // _ASSIMP_APPNODE_H_