Browse Source

Fixes vertex weight assignments.
Adds upaxis override option to match collada importer.

OTHGMars 6 years ago
parent
commit
bc722a353d

+ 56 - 52
Engine/source/ts/assimp/assimpAppMesh.cpp

@@ -37,6 +37,15 @@ AssimpAppMesh::AssimpAppMesh(const struct aiMesh* mesh, AssimpAppNode* node)
    : mMeshData(mesh), appNode(node)
    : mMeshData(mesh), appNode(node)
 {
 {
    Con::printf("[ASSIMP] Mesh Created: %s", getName());
    Con::printf("[ASSIMP] Mesh Created: %s", getName());
+
+   // See if it's a skinned mesh
+   mIsSkinMesh = false;
+   for (U32 b = 0; b < mesh->mNumBones; b++)
+      if (mMeshData->mBones[b]->mNumWeights > 0)
+      {
+         mIsSkinMesh = true;
+         break;
+      }
 }
 }
 
 
 const char* AssimpAppMesh::getName(bool allowFixed)
 const char* AssimpAppMesh::getName(bool allowFixed)
@@ -64,7 +73,6 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objOffset)
    // After this function, the following are expected to be populated:
    // After this function, the following are expected to be populated:
    //     points, normals, uvs, primitives, indices
    //     points, normals, uvs, primitives, indices
    // There is also colors and uv2s but those don't seem to be required.
    // There is also colors and uv2s but those don't seem to be required.
-
    points.reserve(mMeshData->mNumVertices);
    points.reserve(mMeshData->mNumVertices);
    uvs.reserve(mMeshData->mNumVertices);
    uvs.reserve(mMeshData->mNumVertices);
    normals.reserve(mMeshData->mNumVertices);
    normals.reserve(mMeshData->mNumVertices);
@@ -85,10 +93,8 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objOffset)
 
 
       tmpVert = Point3F(pt.x, pt.y, pt.z);
       tmpVert = Point3F(pt.x, pt.y, pt.z);
       tmpNormal = Point3F(nrm.x, nrm.y, nrm.z);
       tmpNormal = Point3F(nrm.x, nrm.y, nrm.z);
-      //AssimpAppNode::convertPoint(tmpVert);
-      //AssimpAppNode::convertPoint(tmpNormal);
 
 
-      //objOffset.mulP(tmpVert);
+      objOffset.mulP(tmpVert);
 
 
       points.push_back(tmpVert);
       points.push_back(tmpVert);
 
 
@@ -126,7 +132,6 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objOffset)
    }
    }
 
 
    U32 numFaces = mMeshData->mNumFaces;
    U32 numFaces = mMeshData->mNumFaces;
-   U32 primCount = 0;
    primitives.reserve(numFaces);
    primitives.reserve(numFaces);
 
 
    //Fetch the number of indices
    //Fetch the number of indices
@@ -138,28 +143,6 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objOffset)
 
 
    indices.reserve(indicesCount);
    indices.reserve(indicesCount);
 
 
-   /*U32 idxCount = 0;
-
-   for (U32 j = 0; j<mModel->mMaterials.size(); j++)
-   {
-      MikuModel::Material &mat = mModel->mMaterials[j];
-      U32 nextIdxCount = idxCount + mat.numIndices;
-
-      primitives.increment();
-
-      TSDrawPrimitive& primitive = primitives.last();
-      primitive.start = indices.size();
-      primitive.matIndex = (TSDrawPrimitive::Triangles | TSDrawPrimitive::Indexed) | j;
-      primitive.numElements = mat.numIndices;
-
-      for (U32 i = idxCount; i<nextIdxCount; i++)
-      {
-         indices.push_back(mModel->mIndices[i]);
-      }
-
-      idxCount = nextIdxCount;
-   }*/
-
    for ( U32 n = 0; n < mMeshData->mNumFaces; ++n)
    for ( U32 n = 0; n < mMeshData->mNumFaces; ++n)
    {
    {
       const struct aiFace* face = &mMeshData->mFaces[n];
       const struct aiFace* face = &mMeshData->mFaces[n];
@@ -191,11 +174,6 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objOffset)
                indices.push_back(index);
                indices.push_back(index);
             }
             }
          }
          }
-
-         // Load the indices in.
-         //indices.push_back(face->mIndices[0]);
-         //indices.push_back(face->mIndices[1]);
-         //indices.push_back(face->mIndices[2]);
       } 
       } 
       else 
       else 
       {
       {
@@ -204,41 +182,67 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objOffset)
    }
    }
 
 
    U32 boneCount = mMeshData->mNumBones;
    U32 boneCount = mMeshData->mNumBones;
-
    bones.setSize(boneCount);
    bones.setSize(boneCount);
 
 
+   // Count the total number of weights for all of the bones.
+   U32 totalWeights = 0;
+   U32 nonZeroWeights = 0;
+   for (U32 b = 0; b < boneCount; b++)
+      totalWeights += mMeshData->mBones[b]->mNumWeights;
+
+   // Assimp gives weights sorted by bone index. We need them in vertex order.
+   Vector<F32> tmpWeight;
+   Vector<S32> tmpBoneIndex;
+   Vector<S32> tmpVertexIndex;
+   tmpWeight.setSize(totalWeights);
+   tmpBoneIndex.setSize(totalWeights);
+   tmpVertexIndex.setSize(totalWeights);
+
    for (U32 b = 0; b < boneCount; b++)
    for (U32 b = 0; b < boneCount; b++)
    {
    {
       String name = mMeshData->mBones[b]->mName.C_Str();
       String name = mMeshData->mBones[b]->mName.C_Str();
+      aiNode* nodePtr = AssimpAppNode::findChildNodeByName(mMeshData->mBones[b]->mName.C_Str(), appNode->mScene->mRootNode);
+      bones[b] = new AssimpAppNode(appNode->mScene, nodePtr);
 
 
       MatrixF boneTransform;
       MatrixF boneTransform;
-      boneTransform.setRow(0, Point4F(mMeshData->mBones[b]->mOffsetMatrix.a1, mMeshData->mBones[b]->mOffsetMatrix.a2, mMeshData->mBones[b]->mOffsetMatrix.a3, mMeshData->mBones[b]->mOffsetMatrix.a4));
-      boneTransform.setRow(1, Point4F(mMeshData->mBones[b]->mOffsetMatrix.b1, mMeshData->mBones[b]->mOffsetMatrix.b2, mMeshData->mBones[b]->mOffsetMatrix.b3, mMeshData->mBones[b]->mOffsetMatrix.b4));
-      boneTransform.setRow(2, Point4F(mMeshData->mBones[b]->mOffsetMatrix.c1, mMeshData->mBones[b]->mOffsetMatrix.c2, mMeshData->mBones[b]->mOffsetMatrix.c3, mMeshData->mBones[b]->mOffsetMatrix.c4));
-      boneTransform.setRow(3, Point4F(mMeshData->mBones[b]->mOffsetMatrix.d1, mMeshData->mBones[b]->mOffsetMatrix.d2, mMeshData->mBones[b]->mOffsetMatrix.d3, mMeshData->mBones[b]->mOffsetMatrix.d4));
-
-      //boneTransform.inverse();
-      //AssimpAppNode::convertMat(boneTransform);
-      //boneTransform.inverse();
+      AssimpAppNode::assimpToTorqueMat(mMeshData->mBones[b]->mOffsetMatrix, boneTransform);
       initialTransforms.push_back(boneTransform);
       initialTransforms.push_back(boneTransform);
 
 
       //Weights
       //Weights
       U32 numWeights = mMeshData->mBones[b]->mNumWeights;
       U32 numWeights = mMeshData->mBones[b]->mNumWeights;
 
 
-      weight.setSize(numWeights);
-      vertexIndex.setSize(numWeights);
-      boneIndex.setSize(numWeights);
-
       for (U32 w = 0; w < numWeights; ++w)
       for (U32 w = 0; w < numWeights; ++w)
       {
       {
          aiVertexWeight* aiWeight = &mMeshData->mBones[b]->mWeights[w];
          aiVertexWeight* aiWeight = &mMeshData->mBones[b]->mWeights[w];
 
 
-         weight[w] = aiWeight->mWeight;
-         vertexIndex[w] = aiWeight->mVertexId;
-         boneIndex[w] = b;
-         //vertWeight. = aiWeight->
+         if (aiWeight->mWeight > 0.0f)
+         {
+            tmpWeight[nonZeroWeights] = aiWeight->mWeight;
+            tmpVertexIndex[nonZeroWeights] = aiWeight->mVertexId;
+            tmpBoneIndex[nonZeroWeights] = b;
+            nonZeroWeights++;
+         }
+      }
+   }
+
+   weight.setSize(nonZeroWeights);
+   vertexIndex.setSize(nonZeroWeights);
+   boneIndex.setSize(nonZeroWeights);
+
+   // Copy the weights to our vectors in vertex order
+   U32 nextWeight = 0;
+   for (U32 i = 0; i < mMeshData->mNumVertices; i++)
+   {
+      for (U32 ind = 0; ind < nonZeroWeights; ind++)
+      {
+         if (tmpVertexIndex[ind] == i)
+         {
+            weight[nextWeight] = tmpWeight[ind];
+            vertexIndex[nextWeight] = tmpVertexIndex[ind];
+            boneIndex[nextWeight] = tmpBoneIndex[ind];
+            nextWeight++;
+         }
       }
       }
-      //= mNumWeights
    }
    }
 
 
    if ( noUVFound )
    if ( noUVFound )
@@ -246,8 +250,8 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objOffset)
 }
 }
 
 
 void AssimpAppMesh::lookupSkinData()
 void AssimpAppMesh::lookupSkinData()
-{
-
+{  // This function is intentionally left blank. The skin data - bones, weights and indexes are
+   // processed in lockMesh() with the rest of the mesh data.
 }
 }
 
 
 F32 AssimpAppMesh::getVisValue(F32 t)
 F32 AssimpAppMesh::getVisValue(F32 t)

+ 2 - 1
Engine/source/ts/assimp/assimpAppMesh.h

@@ -40,6 +40,7 @@ class AssimpAppMesh : public AppMesh
 protected:
 protected:
    class AssimpAppNode* appNode;                     ///< Pointer to the node that owns this mesh
    class AssimpAppNode* appNode;                     ///< Pointer to the node that owns this mesh
    const struct aiMesh* mMeshData;
    const struct aiMesh* mMeshData;
+   bool mIsSkinMesh;
 
 
 public:
 public:
 
 
@@ -100,7 +101,7 @@ public:
    /// Return true if this mesh is a skin
    /// Return true if this mesh is a skin
    bool isSkin()
    bool isSkin()
    {
    {
-      return false;
+      return mIsSkinMesh;
    }
    }
 
 
    /// Generate the vertex, normal and triangle data for the mesh.
    /// Generate the vertex, normal and triangle data for the mesh.

+ 41 - 11
Engine/source/ts/assimp/assimpAppNode.cpp

@@ -156,21 +156,51 @@ void AssimpAppNode::assimpToTorqueMat(const aiMatrix4x4& inAssimpMat, MatrixF& o
 
 
 void AssimpAppNode::convertMat(MatrixF& outMat)
 void AssimpAppNode::convertMat(MatrixF& outMat)
 {
 {
-   if (Con::getBoolVariable("$Assimp::SwapYZ", false))
+   MatrixF rot(true);
+
+   // This is copied directly from ColladaUtils::convertTransform()
+   // ColladaUtils::getOptions().upAxis has been temporarily replaced with $Assimp::OverrideUpAxis for testing
+   // We need a plan for how the full set of assimp import options and settings is going to be managed.
+   switch (Con::getIntVariable("$Assimp::OverrideUpAxis", 2))
    {
    {
-      MatrixF rotMat(EulerF(-M_HALFPI_F, 0, 0));
-      Point3F pos = outMat.getPosition();
-      outMat.mulL(rotMat);
-      rotMat.mulP(pos);
-      outMat.setPosition(pos);
+   case 0: //UPAXISTYPE_X_UP:
+      // rotate 90 around Y-axis, then 90 around Z-axis
+      rot(0, 0) = 0.0f;  rot(1, 0) = 1.0f;
+      rot(1, 1) = 0.0f;	rot(2, 1) = 1.0f;
+      rot(0, 2) = 1.0f;	rot(2, 2) = 0.0f;
+
+      // pre-multiply the transform by the rotation matrix
+      outMat.mulL(rot);
+      break;
+
+   case 1: //UPAXISTYPE_Y_UP:
+      // rotate 180 around Y-axis, then 90 around X-axis
+      rot(0, 0) = -1.0f;
+      rot(1, 1) = 0.0f;	rot(2, 1) = 1.0f;
+      rot(1, 2) = 1.0f;	rot(2, 2) = 0.0f;
+
+      // pre-multiply the transform by the rotation matrix
+      outMat.mulL(rot);
+      break;
+
+   case 2: //UPAXISTYPE_Z_UP:
+   default:
+      // nothing to do
+      break;
    }
    }
 }
 }
 
 
-void AssimpAppNode::convertPoint(Point3F& outPoint)
+aiNode* AssimpAppNode::findChildNodeByName(const char* nodeName, aiNode* rootNode)
 {
 {
-   if (Con::getBoolVariable("$Assimp::SwapYZ", false))
+   aiNode* retNode = NULL;
+   if (strcmp(nodeName, rootNode->mName.C_Str()) == 0)
+      return rootNode;
+
+   for (U32 i = 0; i < rootNode->mNumChildren; ++i)
    {
    {
-      MatrixF rotMat(EulerF(-M_HALFPI_F, 0, 0));
-      rotMat.mulP(outPoint);
+      retNode = findChildNodeByName(nodeName, rootNode->mChildren[i]);
+      if (retNode)
+         return retNode;
    }
    }
-}
+   return nullptr;
+}

+ 1 - 1
Engine/source/ts/assimp/assimpAppNode.h

@@ -107,7 +107,7 @@ public:
 
 
    static void assimpToTorqueMat(const aiMatrix4x4& inAssimpMat, MatrixF& outMat);
    static void assimpToTorqueMat(const aiMatrix4x4& inAssimpMat, MatrixF& outMat);
    static void convertMat(MatrixF& outMat);
    static void convertMat(MatrixF& outMat);
-   static void convertPoint(Point3F& outPoint);
+   static aiNode* findChildNodeByName(const char* nodeName, aiNode* rootNode);
 };
 };
 
 
 #endif // _ASSIMP_APPNODE_H_
 #endif // _ASSIMP_APPNODE_H_