[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:


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







More information about the osg-users mailing list