Tutorials
Analysing a Scenegraph
- Details
- Category: Tutorials
- Published: 02 October 2012
- Written by openscenegraph
- Hits: 74983
Once a scenegraph is loaded you may wish to analyse the in memory tree of nodes. Ideally you would use a nodevisitor, but here is a simple piece of C++ code that works:
void analyseGeode(osg::Geode *geode);
void analysePrimSet(osg::PrimitiveSet*prset, const osg::Vec3Array *verts);
void analyse(osg::Node *nd) {
/// here you have found a group.
osg::Geode *geode = dynamic_cast<osg::Geode *> (nd);
if (geode) { // analyse the geode. If it isnt a geode the dynamic cast gives NULL.
analyseGeode(geode);
} else {
osg::Group *gp = dynamic_cast<osg::Group *> (nd);
if (gp) {
osg::notify(osg::WARN) << "Group "<< gp->getName() <<std::endl;
for (unsigned int ic=0; ic<gp->getNumChildren(); ic++) {
analyse(gp->getChild(ic));
}
} else {
osg::notify(osg::WARN) << "Unknown node "<< nd <<std::endl;
}
}
}
// divide the geode into its drawables and primitivesets:
void analyseGeode(osg::Geode *geode) {
for (unsigned int i=0; i<geode->getNumDrawables(); i++) {
osg::Drawable *drawable=geode->getDrawable(i);
osg::Geometry *geom=dynamic_cast<osg::Geometry *> (drawable);
for (unsigned int ipr=0; ipr<geom->getNumPrimitiveSets(); ipr++) {
osg::PrimitiveSet* prset=geom->getPrimitiveSet(ipr);
osg::notify(osg::WARN) << "Primitive Set "<< ipr << std::endl;
analysePrimSet(prset, dynamic_cast<const osg::Vec3Array*>(geom->getVertexArray()));
}
}
}
void analysePrimSet(osg::PrimitiveSet*prset, const osg::Vec3Array *verts) {
unsigned int ic;
unsigned int i2;
unsigned int nprim=0;
osg::notify(osg::WARN) << "Prim set type "<< prset->getMode() << std::endl;
for (ic=0; ic<prset->getNumIndices(); ic++) { // NB the vertices are held in the drawable -
osg::notify(osg::WARN) << "vertex "<< ic << " is index "<<prset->index(ic) << " at " <<
(* verts)[prset->index(ic)].x() << "," <<
(* verts)[prset->index(ic)].y() << "," <<
(* verts)[prset->index(ic)].z() << std::endl;
}
// you might want to handle each type of primset differently: such as:
switch (prset->getMode()) {
case osg::PrimitiveSet::TRIANGLES: // get vertices of triangle
osg::notify(osg::WARN) << "Triangles "<< nprim << " is index "<<prset->index(ic) << std::endl;
for (i2=0; i2<prset->getNumIndices()-2; i2+=3) {
}
break;
case osg::PrimitiveSet::TRIANGLE_STRIP: // look up how tristrips are coded
break;
// etc for all the primitive types you expect. EG quads, quadstrips lines line loops....
}
}
This code can be inserted into (say) osgviewer.cpp, and called thus:
analyse(loadedModel.get());