[osg-users] Load OSG trimesh to ODE: Read Vertices from Mesh after Loading with osgDB::readNodeFile

Tom Koller tomlucas at uni-bremen.de
Mon Aug 6 03:44:30 PDT 2018

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:


#include <osg/NodeVisitor>
#include <osg/Shape>
#include <ode/ode.h>
class MeshVisitor: public osg::NodeVisitor {
	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();
	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

#include "MeshVisitor.hpp"

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

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

void MeshVisitor::apply(osg::Node& node){

int dTriCallback (dGeomID TriMesh, dGeomID RefObject, int 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
			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++){
		//Make sure geometry is updated to be centered
		dTriMeshDataID mesh=dGeomTriMeshDataCreate();
		dGeomTriMeshDataBuildSimple (mesh,(double *)ode_vertices, vertices->getNumElements(),indices,triangles->getNumIndices());
		geom=dCreateTriMesh(space,mesh, dTriCallback, NULL, NULL);

		//save data of trimeshes

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

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

osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(filename);
zavi::osg_ode::MeshVisitor mv(space);
//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


Read this topic online here:

More information about the osg-users mailing list