Discussion:
[osg-users] Load OSG trimesh to ODE: Read Vertices from Mesh after Loading with osgDB::readNodeFile
Tom Koller
2018-08-06 10:44:30 UTC
Permalink
So here is hot it is done:


One can use a custom class extending NodeVisitor to "vist" all geometries in a node and extract the data:


Code:

//Meshvisitor.hpp
#include <osg/NodeVisitor>
#include <osg/Shape>
#include <ode/ode.h>
class MeshVisitor: public osg::NodeVisitor {
public:
static std::vector<dVector3 *> vertice_allocs;
static std::vector<dTriIndex *> index_allocs;
dGeomID geom; // the resulting geometry

MeshVisitor(dSpaceID space);
virtual ~MeshVisitor();

/**
* Traverses all children of the given node
*
* @param node to traverse
*/
virtual void apply(osg::Node& node);

/**
* Extract vertice data from Geometry
*
* @param geometry Geometry to extract data from
*/
virtual void apply(osg::Geometry& geometry);

/**
* Clears up all allocated memorys
*
* Must call to prevent Memoryleaks at end of application
*/
static void finishMeshes();
private:
dSpaceID space; // and ode space for the resulting geometry
};





the apply functions are called on every node /geometry in the given node.
the class needs a ode space to create the ode object from the osg mesh


the cpp looks as follows




Code:
#include "MeshVisitor.hpp"

#include <osg/Geometry>
#include <iostream>
#include <ode/ode.h>
MeshVisitor::MeshVisitor(dSpaceID space): geom(),space(space) {
// TODO Auto-generated constructor stub
setTraversalMode(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN);
}

MeshVisitor::~MeshVisitor() {
// TODO Auto-generated destructor stub
}


void MeshVisitor::apply(osg::Node& node){
traverse(node);
}


int dTriCallback (dGeomID TriMesh, dGeomID RefObject, int TriangleIndex){
//printf(TriangleIndex);
return 1;
}

void MeshVisitor::apply(osg::Geometry& geometry){

// Read vertices and triangles
osg::Vec3Array *vertices =dynamic_cast<osg::Vec3Array*> (geometry.getVertexArray()); //< 3d vertice array cast
auto triangles=(geometry.getPrimitiveSet(0)); //the triangle primitives (can have multiple primitive sets)
std::cout <<geometry.getNumPrimitiveSets()<< std::endl;
std::cout <<triangles->getMode()<< std::endl;
// create ode containers
dVector3 *ode_vertices= new dVector3[vertices->getNumElements()];
dTriIndex *indices=new dTriIndex[triangles->getNumIndices()];
std::cout <<triangles->getNumIndices() << std::endl;
auto center= geometry.getBound().center(); //<center to center it on COM
std::cout << center[0] << " "<<center [1]<< " "<<center [2]<< std::endl;

for (unsigned int i = 0; i < vertices->getNumElements(); i++) {
// calc vertex relative to center
(*vertices)[i]-=center;
osg::Vec3d temp = (*vertices)[i];
memcpy(ode_vertices[i],&temp,3*sizeof(double)); // copy data to ode array
std::cout << temp[0] << " " << temp[1] << " " << temp[2] <<std::endl;

std::cout << ode_vertices[i][0] << " " << ode_vertices[i][1] << " " << ode_vertices[i][2] <<std::endl;
}
for(unsigned int i=0; i < triangles->getNumIndices();i++){
indices[i]=triangles->index(i);
}
//Make sure geometry is updated to be centered
geometry.setVertexArray(vertices);
dTriMeshDataID mesh=dGeomTriMeshDataCreate();
dGeomTriMeshDataBuildSimple (mesh,(double *)ode_vertices, vertices->getNumElements(),indices,triangles->getNumIndices());
geom=dCreateTriMesh(space,mesh, dTriCallback, NULL, NULL);

//save data of trimeshes
vertice_allocs.push_back(ode_vertices);
index_allocs.push_back(indices);
}

void MeshVisitor::finishMeshes(){
for(auto element : vertice_allocs)
delete element;
for(auto element : index_allocs)
delete element;
vertice_allocs.clear();
index_allocs.clear();
}

std::vector<dVector3*> MeshVisitor::vertice_allocs;
std::vector<dTriIndex *> MeshVisitor::index_allocs;





the triangles are stored as 3d vertices in geometry.getVertexArray()
which indices form a triangle are stored in the primitivesets
be carefull to check that your object file only contains 1 mesh with primitive type triangle for this code to work
since there are sometimes offsets in the obj file, the geometry is centered \\

the static function Meshvisitor::finishMeshes makes sure, that all allocated data for the ode meshes gets destroyed in the end\\

the dTriCallback determines whether a triangle with given index can collide in ode with other objects, its set to true for all indizes\\


mesh data can then be loaded to ode with using


Code:
osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(filename);
zavi::osg_ode::MeshVisitor mv(space);
node->accept(mv);
//mesh is now stored in mv.geom




this only works if only one mesh is in the object file and if it is using triangle primitives. as far as i observed meshing an object with blender and exporting it fullfills this.


Hope someone can use this

Cheers
[/code]

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=74472#74472

Loading...