Skip to content

Hey, Nick! Awesome addon :) This issue is about slow performance... #24

@redgpu

Description

@redgpu

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

Image

As you can see at the top left corner, the printed time difference for fbxLateUpdate(fbx) (which is a Game Script function that directly calls fbx->lateUpdate() method here) is 7 milliseconds, which is... a lot! 😄

All 7 milliseconds are spent here, in this Mesh::updateMesh function alone:

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;
}
}

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! 😃

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions