|
void Mesh::updateMesh( ofMesh* aMesh, FbxTime& pTime, FbxAnimLayer * pAnimLayer, FbxPose* pPose ) { |
|
const bool lHasShape = fbxMesh->GetShapeCount() > 0; |
|
const bool lHasSkin = fbxMesh->GetDeformerCount(FbxDeformer::eSkin) > 0; |
|
const bool lHasVertexCache = fbxMesh->GetDeformerCount(FbxDeformer::eVertexCache); |
|
const bool lHasDeformation = lHasShape || lHasSkin; |
|
|
|
const int lVertexCount = fbxMesh->GetControlPointsCount(); |
|
|
|
// cout << "ofxFBXMesh :: " << getName() << " vertices: " << lVertexCount << " has blend shape: " << lHasShape << " has skin: " << lHasSkin << " has def: " << lHasDeformation << " has vertex cache: " << lHasVertexCache << " | " << ofGetFrameNum() << endl; |
|
|
|
if(!lHasDeformation || lVertexCount < 3) return; |
|
|
|
FbxAMatrix lGlobalOffPosition = mFbxGlobalPosition * mGeometryOffset; |
|
|
|
// FbxAMatrix lGlobalPosition = GetGlobalPosition( fbxMesh->GetNode(), pTime, pPose ); |
|
// FbxAMatrix lGlobalPosition = GetGlobalPosition( fbxMesh->GetNode(), pTime ); |
|
|
|
// Geometry offset. |
|
// it is not inherited by the children. |
|
// this is now set in the setup function |
|
// FbxAMatrix lGeometryOffset = GetGeometry( fbxMesh->GetNode() );//, FbxNode::eDestinationPivot ); |
|
// FbxAMatrix lGlobalOffPosition = lGlobalPosition * mGeometryOffset;//lGeometryOffset; |
|
|
|
FbxVector4* lVertexArray = NULL; |
|
lVertexArray = new FbxVector4[ lVertexCount ]; |
|
memcpy( lVertexArray, fbxMesh->GetControlPoints(), lVertexCount * sizeof(FbxVector4) ); |
|
|
|
FbxVector4* lNormalArray = NULL; |
|
if( aMesh->hasNormals() && aMesh->usingNormals() ) { |
|
if( mNormalsArray != NULL ) { |
|
// cout << "updateMesh :: aMesh " << aMesh->hasNormals() << " using: " << aMesh->usingNormals() << endl; |
|
lNormalArray = new FbxVector4[ lVertexCount ]; |
|
memcpy( lNormalArray, mNormalsArray, lVertexCount * sizeof(FbxVector4) ); |
|
} |
|
} |
|
|
|
|
|
if(lHasShape) { |
|
computeBlendShapes( aMesh, pTime, pAnimLayer ); |
|
} |
|
if(lHasSkin) { |
|
//we need to get the number of clusters. which are controlled by bones // |
|
// const int lSkinCount = fbxMesh->GetDeformerCount(FbxDeformer::eSkin); |
|
// int lClusterCount = 0; |
|
// for (int lSkinIndex = 0; lSkinIndex < lSkinCount; ++lSkinIndex) { |
|
// lClusterCount += ((FbxSkin *)(fbxMesh->GetDeformer(lSkinIndex, FbxDeformer::eSkin)))->GetClusterCount(); |
|
// } |
|
int lClusterCount = getNumClusters(); |
|
if (lClusterCount) { |
|
computeSkinDeformation( lGlobalOffPosition, pTime, pAnimLayer, lVertexArray, lNormalArray, pPose ); |
|
} |
|
} |
|
// cout << "Calling update mesh lHasShape = " << lHasShape << " skin = " << lHasSkin << " lHasDeformation = " << lHasDeformation << endl; |
|
|
|
|
|
vector< glm::vec3 >& amverts = aMesh->getVertices(); |
|
vector< glm::vec3 >& amnormals = aMesh->getNormals(); |
|
|
|
bool bUpdateNormals = lNormalArray != NULL && amnormals.size() > 1; |
|
|
|
const int controlPointCount = fbxMesh->GetControlPointsCount(); |
|
// update the vertices // |
|
for(int i = 0; i < controlPointCount; i++ ) { |
|
amverts[i] = glm::vec3( lVertexArray[i][0], lVertexArray[i][1], lVertexArray[i][2] ); |
|
} |
|
|
|
if( bUpdateNormals ) { |
|
if( mNormalMappingMode == FbxGeometryElement::eByControlPoint ) { |
|
for(int i = 0; i < controlPointCount; i++ ) { |
|
amnormals[i] = glm::vec3( lNormalArray[i][0], lNormalArray[i][1], lNormalArray[i][2] ); |
|
} |
|
} else if( mNormalMappingMode == FbxGeometryElement::eByPolygonVertex ) { |
|
const int lPolygonCount = fbxMesh->GetPolygonCount(); |
|
int polysize = 3; |
|
|
|
for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex) { |
|
polysize = fbxMesh->GetPolygonSize( lPolygonIndex ); |
|
for (int lVerticeIndex = 0; lVerticeIndex < polysize; ++lVerticeIndex) { |
|
|
|
const int lControlPointIndex = fbxMesh->GetPolygonVertex( lPolygonIndex, lVerticeIndex ); |
|
amnormals[lControlPointIndex] = glm::vec3(lNormalArray[ lControlPointIndex ][0], |
|
lNormalArray[ lControlPointIndex ][1], |
|
lNormalArray[ lControlPointIndex ][2] ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
delete [] lVertexArray; |
|
if( lNormalArray != NULL ) { |
|
delete [] lNormalArray; |
|
} |
|
|
|
} |
Hi, Nick!
First of all, thank you for this addon! I use it for my OF-based app called Game Script (script version, native C/C++ version) that allows to code in C and C++ and compile the code at runtime.
Here's an example of code that draws a Mixamo FBX mesh using your addon:
https://pastebin.com/raw/Cnkbg7Zt
As you can see at the top left corner, the printed time difference for
fbxLateUpdate(fbx)(which is a Game Script function that directly callsfbx->lateUpdate()method here) is 7 milliseconds, which is... a lot! 😄All 7 milliseconds are spent here, in this
Mesh::updateMeshfunction alone:ofxFBX/src/FBXSource/ofxFBXSrcMesh.cpp
Lines 586 to 679 in f032fd4
I know it's the heaviest function, but it can take less than 7 milliseconds... I will rewrite it at some point, just letting you know about this issue!
Thank you again for this awesome addon! 😃