ofxAssimpModelLoader: how to tweak model meshes?

Anyone has an idea about how to dynamically change the internal meshes of an ofxAssimpLoader?
In particular I need to move some single vertices of the mesh every frame.

I saw that internally the type aiMesh is used and a mesh helper is used to wrap aiMesh for draw() but I have no idea how to tweak them without too much hassle.

Of course ofMeshes can be obtained by loader.getMesh(idx) or loader.getCurrentAnimatedMesh(idx), so I could directly access vertices of those “copies” and change them.
And after I could draw the meshes independently from the loader.

In a short pseudo code I’m trying this
BTW: I checked my file has only 1 mesh so for now I get only mesh(0).

ofMesh mesh;
ofxAssimpModelLoader loader;
ofCamera cam;

void setup()
{
   loader.loadModel("modelFile.obj");
   mesh = loader.getMesh(0);
}

void draw()
{
   for(int i = 0;  i < mesh.getNumVertices();  i++)
   {
      mesh.getVertex(i).x = someNewValue;
      mesh.getVertex(i).y = someNewValue;
      mesh.getVertex(i).z = someNewValue;
   }

   cam.begin();
   mesh.drawFaces();
   cam.end():
}

But it does not work, what I get is a blank window, even if I don’t touch vertices.

If I instead do

void draw()
{
  cam.begin();
  loader.drawFaces();
  cam.end():
}

the model is shown correctly with colors and textures.
So I’m pretty sure I’m doing something wrong and/or I’m misunderstanding something.

Actually these are two questions, I will be happy if someone knows the answer for at least one…

UPDATE

If anyone is interested, i found that the only way to modify model’s meshes vertices is by adding a function to the addon, in ofxAssimpModelLoader.h file.

I added a public function to get an ofxAssimpMeshHelper pointer for the mesh I’d like to tweak, from a protected internal vector which holds all the model mesh helpers;

This way I can access:

  • the cached model mesh, which holds the vertices set up by the loadModel() function
  • the vbo which gets redrawn in drawFaces() and which needs to be updated after mesh tweaking

addons/ofxAssimpModelLoader/libs/assimp/src/ofxAssimpModelLoader.h

// add this  somewhere before the "protected" statement
public:

ofxAssimpMeshHelper* getModelMeshHelper(int i) { return &modelMeshes[i]; }

protected:
.................

This is an example of how to use it.
It’s a modification of “3DModelLoaderExample” project in the examples folder.
The penguin model becomes “sparkling” by adding every frame a random value to all the vertices’ xyz coordinates

3DModelLoaderExample.cpp

void ofApp::draw()
{
	// so the model isn't see through.
	ofEnableDepthTest();
    light.enable();

	cam.begin();

	if (bUsingMesh){
		// draws the ply file loaded into the mesh is you pressed 
		meshNode.transformGL();
		mesh.drawFaces();
		meshNode.restoreTransformGL();
	} 
	else 
	{
		/////////////////////////////////////////////////////////////////////////////////
        // modified part starts here
        /////////////////////////////////////////////////////////////////////////////////

        // the mesh helper: it exposes pointers to some internal data structs and variables  
		ofxAssimpMeshHelper* helper = model.getModelMeshHelper(0); 

        // pointer to an internal ofMesh exposed by the helper, which holds a copy 
        // of the model's vertices: it is used by ofxAssimpModelLoader drawing methods
		ofMesh* cachedMesh = &helper->cachedMesh; 

        // model vertices loaded from the file are stored in an internal aiMesh struct, 
        // which is exposed by the helper; their xyz coordinates are copied 
        // to cachedMesh vertices but adding some random values
		for (int i = 0; i < cachedMesh->getVertices().size(); i++) 
		{
			cachedMesh->getVertices().at(i).x = helper->mesh->mVertices[i].x + ofRandom(-0.01, 0.01);
			cachedMesh->getVertices().at(i).y = helper->mesh->mVertices[i].y + ofRandom(-0.01, 0.01);
			cachedMesh->getVertices().at(i).z = helper->mesh->mVertices[i].z + ofRandom(-0.01, 0.01);
		}

        // update internal vbo before model drawing
		helper->vbo.updateMesh(*cachedMesh); 

	    /////////////////////////////////////////////////////////////////////////////////
        // modified part ends here
        /////////////////////////////////////////////////////////////////////////////////

		model.drawFaces();
    }

	cam.end();

    light.disable();
	ofDisableDepthTest();
    
    // display help text if it is enable
    if(bHelpText) {
        stringstream ss;
        ss << "FPS: " << ofToString(ofGetFrameRate(),0) << endl << endl;
        ss << "(1/2/3/4/5/6): load different file types"<<endl;
        ss << "Current file info: " + curFileInfo <<endl;
        if(bUsingMesh){
            ss << "Use ofEasyCam mouse and key controls to navigate."<< endl <<endl;
        }
        ss <<"(h): Toggle help."<<endl;
        ofDrawBitmapString(ss.str().c_str(), 20, 20);
    }
}
1 Like

Thanks mate, super useful