Created
December 1, 2017 09:01
-
-
Save fulezi/95a9ac319fd1cbeca1b18a4cde3986dc to your computer and use it in GitHub Desktop.
OpenSceneGraph - Display model normals
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "CollectNormalsVisitor.hpp" | |
#include <cassert> | |
#include <osg/Geode> | |
#include <osg/Geometry> | |
namespace ose { | |
CollectNormalsVisitor::CollectNormalsVisitor(const float magnitude) | |
: NodeVisitor(osg::NodeVisitor::TraversalMode::TRAVERSE_ACTIVE_CHILDREN) | |
, magnitude(magnitude) | |
{ | |
} | |
void CollectNormalsVisitor::apply(osg::Geode& geode) | |
{ | |
for (unsigned int it = 0; it < geode.getNumDrawables(); ++it) { | |
const osg::Drawable* childDrawable = geode.getDrawable(it); | |
assert(childDrawable); | |
const osg::Geometry* geometry = childDrawable->asGeometry(); | |
/* We only support geometry */ | |
if (geometry) { | |
const osg::Vec3Array* normals = | |
dynamic_cast<const osg::Vec3Array*>(geometry->getNormalArray()); | |
assert(normals); | |
const osg::Vec3Array* vertices = | |
dynamic_cast<const osg::Vec3Array*>(geometry->getVertexArray()); | |
assert(vertices); | |
assert(normals->getBinding() == osg::Array::Binding::BIND_PER_VERTEX && | |
"// TODO: Support other binding mods"); | |
osg::Matrix world = osg::computeWorldToLocal(this->getNodePath()); | |
for (unsigned int it = 0; it < vertices->size(); ++it) { | |
const osg::Vec3& lineBegin = world * (*vertices)[it]; | |
const osg::Vec3& lineEnd = lineBegin + (*normals)[it] * magnitude; | |
normalList.push_back(lineBegin); | |
normalList.push_back(lineEnd); | |
} | |
} else { | |
osg::notify() << "Skipping non-geometry Drawable:" | |
<< childDrawable->getName() << "\n"; | |
} | |
} | |
traverse(geode); | |
} | |
osg::ref_ptr<osg::Geode> CollectNormalsVisitor::toNormalsGeomtery( | |
osg::Vec4 color) | |
{ | |
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array; | |
vertices->insert(vertices->begin(), normalList.begin(), normalList.end()); | |
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array; | |
colors->push_back(color); | |
osg::ref_ptr<osg::Geometry> norms = new osg::Geometry; | |
norms->setVertexArray(vertices); | |
norms->setColorArray(colors); | |
norms->setColorBinding(osg::Geometry::BIND_OVERALL); | |
norms->addPrimitiveSet(new osg::DrawArrays(GL_LINES, 0, vertices->size())); | |
osg::ref_ptr<osg::Geode> leaf = new osg::Geode; | |
// Make sure to deactivate the lighting | |
leaf->getOrCreateStateSet()->setMode( | |
GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED); | |
leaf->addDrawable(norms); | |
return leaf; | |
} | |
} // ose |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <osg/NodeVisitor> | |
namespace ose { | |
/** | |
* Compute a representation of normals from children geometries. | |
* | |
* Normals are bound to vertices. | |
* The length of each normal is controlled with the magniture parameter. | |
*/ | |
struct CollectNormalsVisitor : public osg::NodeVisitor | |
{ | |
/** Vector of normal lines: [normal1-begin, normal1-end, ...] */ | |
std::vector<osg::Vec3> normalList; | |
float magnitude; | |
CollectNormalsVisitor(const float magnitude = 2.0f); | |
void apply(osg::Geode& geode) override; | |
osg::ref_ptr<osg::Geode> toNormalsGeomtery( | |
osg::Vec4 color = osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f)); | |
}; | |
} // ose |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "CollectNormalsVisitor.hpp" | |
int | |
main(int argc, char** argv) | |
{ | |
// Load your model | |
osg::ref_ptr<osg::Node> model = osgDB::readNodeFile(fileToOpen); | |
// Collect all the geometries normals from parent to children | |
ose::CollectNormalsVisitor c; | |
model->accept(c); | |
// Generate the new geometry (a list of gl_lines) and add them to the root | |
osg::ref_ptr<osg::MatrixTransform> root = new osg::MatrixTransform; | |
root->addChild(c.toNormalsGeomtery(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f))); | |
/* Add the root to the viewer ... */ | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
A quick way to get and display normals with OSG.
Currently only 'standard' geometries with BIND_PER_VERTEX are supported.
But you get the concept. It's easy to go beyond :)