|
@@ -37,6 +37,15 @@ AssimpAppMesh::AssimpAppMesh(const struct aiMesh* mesh, AssimpAppNode* node)
|
|
|
: mMeshData(mesh), appNode(node)
|
|
|
{
|
|
|
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)
|
|
@@ -59,12 +68,11 @@ MatrixF AssimpAppMesh::getMeshTransform(F32 time)
|
|
|
return appNode->getNodeTransform(time);
|
|
|
}
|
|
|
|
|
|
-void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objectOffset)
|
|
|
+void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objOffset)
|
|
|
{
|
|
|
// After this function, the following are expected to be populated:
|
|
|
// points, normals, uvs, primitives, indices
|
|
|
// There is also colors and uv2s but those don't seem to be required.
|
|
|
-
|
|
|
points.reserve(mMeshData->mNumVertices);
|
|
|
uvs.reserve(mMeshData->mNumVertices);
|
|
|
normals.reserve(mMeshData->mNumVertices);
|
|
@@ -74,23 +82,19 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objectOffset)
|
|
|
{
|
|
|
// Points and Normals
|
|
|
aiVector3D pt = mMeshData->mVertices[i];
|
|
|
- aiVector3D nrm = mMeshData->mNormals[i];
|
|
|
+ aiVector3D nrm;
|
|
|
+ if (mMeshData->HasNormals())
|
|
|
+ nrm = mMeshData->mNormals[i];
|
|
|
+ else
|
|
|
+ nrm.Set(0, 0, 0);
|
|
|
|
|
|
Point3F tmpVert;
|
|
|
Point3F tmpNormal;
|
|
|
|
|
|
- if (Con::getBoolVariable("$Assimp::SwapYZ", false))
|
|
|
- {
|
|
|
- tmpVert = Point3F(pt.x, pt.z, pt.y);
|
|
|
- tmpNormal = Point3F(nrm.x, nrm.z, nrm.y);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- tmpVert = Point3F(pt.x, pt.y, pt.z);
|
|
|
- tmpNormal = Point3F(nrm.x, nrm.y, nrm.z);
|
|
|
- }
|
|
|
+ tmpVert = Point3F(pt.x, pt.y, pt.z);
|
|
|
+ tmpNormal = Point3F(nrm.x, nrm.y, nrm.z);
|
|
|
|
|
|
- //objectOffset.mulP(tmpVert);
|
|
|
+ objOffset.mulP(tmpVert);
|
|
|
|
|
|
points.push_back(tmpVert);
|
|
|
|
|
@@ -128,8 +132,7 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objectOffset)
|
|
|
}
|
|
|
|
|
|
U32 numFaces = mMeshData->mNumFaces;
|
|
|
- U32 primCount = 0;
|
|
|
- primitives.reserve(numFaces);
|
|
|
+ //primitives.reserve(numFaces);
|
|
|
|
|
|
//Fetch the number of indices
|
|
|
U32 indicesCount = 0;
|
|
@@ -140,41 +143,18 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objectOffset)
|
|
|
|
|
|
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;
|
|
|
- }*/
|
|
|
+ // Create TSMesh primitive
|
|
|
+ primitives.increment();
|
|
|
+ TSDrawPrimitive& primitive = primitives.last();
|
|
|
+ primitive.start = 0;
|
|
|
+ primitive.matIndex = (TSDrawPrimitive::Triangles | TSDrawPrimitive::Indexed) | (S32)mMeshData->mMaterialIndex;
|
|
|
+ primitive.numElements = indicesCount;
|
|
|
|
|
|
for ( U32 n = 0; n < mMeshData->mNumFaces; ++n)
|
|
|
{
|
|
|
const struct aiFace* face = &mMeshData->mFaces[n];
|
|
|
if ( face->mNumIndices == 3 )
|
|
|
{
|
|
|
- // Create TSMesh primitive
|
|
|
- primitives.increment();
|
|
|
- TSDrawPrimitive& primitive = primitives.last();
|
|
|
- primitive.start = indices.size();
|
|
|
- primitive.matIndex = (TSDrawPrimitive::Triangles | TSDrawPrimitive::Indexed) | (S32)mMeshData->mMaterialIndex;
|
|
|
- //primitive.numElements = face->mNumIndices;//3;
|
|
|
- primitive.numElements = 3;
|
|
|
-
|
|
|
if (Con::getBoolVariable("$Assimp::FlipNormals", true))
|
|
|
{
|
|
|
U32 indexCount = face->mNumIndices;
|
|
@@ -193,11 +173,6 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objectOffset)
|
|
|
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
|
|
|
{
|
|
@@ -206,39 +181,67 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objectOffset)
|
|
|
}
|
|
|
|
|
|
U32 boneCount = mMeshData->mNumBones;
|
|
|
-
|
|
|
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++)
|
|
|
{
|
|
|
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;
|
|
|
-
|
|
|
- for (U32 m = 0; m < 16; ++m)
|
|
|
- {
|
|
|
- boneTransform[m] = *mMeshData->mBones[b]->mOffsetMatrix[m];
|
|
|
- }
|
|
|
-
|
|
|
- //initialTransforms.push_back(boneTransform);
|
|
|
- initialTransforms.push_back(MatrixF::Identity);
|
|
|
+ AssimpAppNode::assimpToTorqueMat(mMeshData->mBones[b]->mOffsetMatrix, boneTransform);
|
|
|
+ initialTransforms.push_back(boneTransform);
|
|
|
|
|
|
//Weights
|
|
|
U32 numWeights = mMeshData->mBones[b]->mNumWeights;
|
|
|
|
|
|
- weight.setSize(numWeights);
|
|
|
- vertexIndex.setSize(numWeights);
|
|
|
-
|
|
|
for (U32 w = 0; w < numWeights; ++w)
|
|
|
{
|
|
|
- aiVertexWeight* aiWeight = mMeshData->mBones[b]->mWeights;
|
|
|
+ aiVertexWeight* aiWeight = &mMeshData->mBones[b]->mWeights[w];
|
|
|
+
|
|
|
+ if (aiWeight->mWeight > 0.0f)
|
|
|
+ {
|
|
|
+ tmpWeight[nonZeroWeights] = aiWeight->mWeight;
|
|
|
+ tmpVertexIndex[nonZeroWeights] = aiWeight->mVertexId;
|
|
|
+ tmpBoneIndex[nonZeroWeights] = b;
|
|
|
+ nonZeroWeights++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- weight[w] = aiWeight->mWeight;
|
|
|
- vertexIndex[w] = aiWeight->mVertexId;
|
|
|
- boneIndex[w] = b;
|
|
|
- //vertWeight. = aiWeight->
|
|
|
+ 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 )
|
|
@@ -246,8 +249,8 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objectOffset)
|
|
|
}
|
|
|
|
|
|
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)
|