Added 'normals' pseudoloader
This commit is contained in:
parent
6624f3aa62
commit
da9de96fae
14
src/osgPlugins/normals/GNUmakefile
Normal file
14
src/osgPlugins/normals/GNUmakefile
Normal file
@ -0,0 +1,14 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
ReaderWriterNormals.cpp\
|
||||
Normals.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(OTHER_LIBS) $(SOCKET_LIBS)
|
||||
|
||||
TARGET_BASENAME = normals
|
||||
include $(TOPDIR)/Make/cygwin_plugin_def
|
||||
PLUGIN = $(PLUGIN_PREFIX)$(TARGET_BASENAME).$(PLUGIN_EXT)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
230
src/osgPlugins/normals/Normals.cpp
Normal file
230
src/osgPlugins/normals/Normals.cpp
Normal file
@ -0,0 +1,230 @@
|
||||
#include "Normals.h"
|
||||
|
||||
using namespace osg;
|
||||
|
||||
Normals::Normals( Node *node, float scale, Mode mode )
|
||||
{
|
||||
MakeNormalsVisitor mnv(scale);
|
||||
mnv.setMode( mode );
|
||||
node->accept( mnv );
|
||||
|
||||
ref_ptr<Vec3Array> coords = mnv.getCoords();
|
||||
ref_ptr<Vec4Array> colors = new Vec4Array;
|
||||
if( mode == SurfaceNormals )
|
||||
colors->push_back( Vec4( 0, 1, 0, 1 ));
|
||||
else if( mode == VertexNormals )
|
||||
colors->push_back( Vec4( 1, 0, 0, 1 ));
|
||||
|
||||
ref_ptr<Geometry> geom = new Geometry;
|
||||
geom->setVertexArray( coords.get() );
|
||||
geom->setColorArray( colors.get() );
|
||||
geom->setColorBinding( Geometry::BIND_OVERALL );
|
||||
|
||||
geom->addPrimitiveSet( new DrawArrays( PrimitiveSet::LINES, 0, coords->size()));
|
||||
|
||||
StateSet *sset = new StateSet;
|
||||
sset->setMode( GL_LIGHTING, StateAttribute::OFF);
|
||||
geom->setStateSet( sset );
|
||||
addDrawable( geom.get() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
Normals::MakeNormalsVisitor::MakeNormalsVisitor( float normalScale, Normals::Mode mode):
|
||||
NodeVisitor(NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
||||
_normal_scale(normalScale),
|
||||
_mode(mode)
|
||||
{
|
||||
_local_coords = new Vec3Array;
|
||||
_mat = osg::Matrix::identity();
|
||||
}
|
||||
|
||||
|
||||
void Normals::MakeNormalsVisitor::apply(osg::MatrixTransform& tx)
|
||||
{
|
||||
_matStack.push( _mat );
|
||||
_mat = _mat * tx.getMatrix();
|
||||
|
||||
traverse( tx );
|
||||
|
||||
_mat = _matStack.top();
|
||||
_matStack.pop();
|
||||
}
|
||||
|
||||
void Normals::MakeNormalsVisitor::apply( Geode &geode )
|
||||
{
|
||||
for( unsigned int i = 0; i < geode.getNumDrawables(); i++ )
|
||||
{
|
||||
Geometry *geom = dynamic_cast<Geometry *>(geode.getDrawable(i));
|
||||
if( geom )
|
||||
{
|
||||
Vec3Array *coords = dynamic_cast<Vec3Array*>(geom->getVertexArray());
|
||||
if( coords == 0L )
|
||||
continue;
|
||||
|
||||
Vec3Array *normals = dynamic_cast<Vec3Array*>(geom->getNormalArray());
|
||||
if( normals == 0L )
|
||||
continue;
|
||||
|
||||
Geometry::AttributeBinding binding = geom->getNormalBinding();
|
||||
if( binding == Geometry::BIND_OFF )
|
||||
continue;
|
||||
|
||||
if( binding == Geometry::BIND_OVERALL )
|
||||
{
|
||||
Vec3 v(0,0,0);
|
||||
Vec3 n = normals->front();
|
||||
|
||||
Vec3Array::iterator coord_index = coords->begin();
|
||||
while( coord_index != coords->end() )
|
||||
v += *(coord_index++) * _mat;
|
||||
v /= (float)(coords->size());
|
||||
|
||||
n *= _normal_scale;
|
||||
_local_coords->push_back( v );
|
||||
_local_coords->push_back( (v + n));
|
||||
}
|
||||
else // BIND_PER_PRIMTIVE_SET, BIND_PER_PRIMTITIV, BIND_PER_VERTEX
|
||||
{
|
||||
Geometry::PrimitiveSetList& primitiveSets = geom->getPrimitiveSetList();
|
||||
Geometry::PrimitiveSetList::iterator itr;
|
||||
|
||||
Vec3Array::iterator coord_index = coords->begin();
|
||||
Vec3Array::iterator normals_index = normals->begin();
|
||||
|
||||
for(itr=primitiveSets.begin(); itr!=primitiveSets.end(); ++itr)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
_printPrimitiveType( (*itr).get() );
|
||||
#endif
|
||||
if( binding == Geometry::BIND_PER_PRIMITIVE_SET )
|
||||
{
|
||||
Vec3 v(0,0,0);
|
||||
Vec3 n = *(normals_index++);
|
||||
int ni = (*itr)->getNumIndices();
|
||||
for( int i = 0; i < ni; i++ )
|
||||
v += *(coord_index++) * _mat;
|
||||
v /= (float)(ni);
|
||||
|
||||
n *= _normal_scale;
|
||||
_local_coords->push_back( v );
|
||||
_local_coords->push_back( (v + n));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
switch((*itr)->getMode())
|
||||
{
|
||||
case(PrimitiveSet::TRIANGLES):
|
||||
for( unsigned int j = 0; j < (*itr)->getNumPrimitives(); j++ )
|
||||
{
|
||||
_processPrimitive( 3, coord_index, normals_index, binding );
|
||||
coord_index += 3;
|
||||
if( binding == Geometry::BIND_PER_PRIMITIVE )
|
||||
normals_index++;
|
||||
else
|
||||
normals_index+=3;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case(PrimitiveSet::TRIANGLE_STRIP):
|
||||
for( unsigned int j = 0; j < (*itr)->getNumIndices()-2; j++ )
|
||||
{
|
||||
_processPrimitive( 3, coord_index, normals_index, binding );
|
||||
coord_index++;
|
||||
normals_index++;
|
||||
}
|
||||
coord_index += 2;
|
||||
if( binding == Geometry::BIND_PER_VERTEX )
|
||||
normals_index += 2;
|
||||
break;
|
||||
|
||||
case(PrimitiveSet::TRIANGLE_FAN):
|
||||
break;
|
||||
|
||||
case(PrimitiveSet::QUADS):
|
||||
for( unsigned int j = 0; j < (*itr)->getNumPrimitives(); j++ )
|
||||
{
|
||||
_processPrimitive( 4, coord_index, normals_index, binding );
|
||||
coord_index += 4;
|
||||
if( binding == Geometry::BIND_PER_PRIMITIVE )
|
||||
normals_index++;
|
||||
else
|
||||
normals_index+=4;
|
||||
}
|
||||
break;
|
||||
|
||||
case(PrimitiveSet::QUAD_STRIP):
|
||||
case(PrimitiveSet::POLYGON):
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
traverse( geode );
|
||||
}
|
||||
|
||||
|
||||
void Normals::MakeNormalsVisitor::_processPrimitive( unsigned int nv,
|
||||
Vec3Array::iterator coords,
|
||||
Vec3Array::iterator normals,
|
||||
Geometry::AttributeBinding binding )
|
||||
{
|
||||
Vec3 v(0,0,0);
|
||||
Vec3 n(0,0,0);
|
||||
if( _mode == SurfaceNormals || binding == Geometry::BIND_PER_PRIMITIVE )
|
||||
{
|
||||
if( binding == Geometry::BIND_PER_PRIMITIVE )
|
||||
{
|
||||
n = *(normals++);
|
||||
}
|
||||
else if( binding == Geometry::BIND_PER_VERTEX )
|
||||
{
|
||||
for( unsigned int i = 0; i < nv; i++ )
|
||||
n += *(normals++);
|
||||
n /= (float)(nv);
|
||||
}
|
||||
|
||||
for( unsigned int i = 0; i < nv; i++ )
|
||||
v += *(coords++) * _mat;
|
||||
v /= (float)(nv);
|
||||
|
||||
n *= _normal_scale;
|
||||
_local_coords->push_back( v );
|
||||
_local_coords->push_back( (v + n));
|
||||
}
|
||||
else if( _mode == VertexNormals )
|
||||
{
|
||||
for( unsigned int i = 0; i < nv; i++ )
|
||||
{
|
||||
v = *(coords++) * _mat;
|
||||
n = *(normals++);
|
||||
n *= _normal_scale;
|
||||
_local_coords->push_back( v );
|
||||
_local_coords->push_back( (v + n));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void Normals::_printPrimitiveType( osg::PrimitiveSet *pset )
|
||||
{
|
||||
std::cout << (
|
||||
pset->getMode() == PrimitiveSet::POINTS ? "POINTS" :
|
||||
pset->getMode() == PrimitiveSet::LINES ? "LINES" :
|
||||
pset->getMode() == PrimitiveSet::LINE_STRIP ? "LINE_STRIP" :
|
||||
pset->getMode() == PrimitiveSet::LINE_LOOP ? "LINE_LOOP" :
|
||||
pset->getMode() == PrimitiveSet::TRIANGLES ? "TRIANGLES" :
|
||||
pset->getMode() == PrimitiveSet::TRIANGLE_STRIP ? "TRIANGLE_STRIP" :
|
||||
pset->getMode() == PrimitiveSet::TRIANGLE_FAN ? "TRIANGLE_FAN" :
|
||||
pset->getMode() == PrimitiveSet::QUADS ? "QUADS" :
|
||||
pset->getMode() == PrimitiveSet::QUAD_STRIP ? "QUAD_STRIP" :
|
||||
pset->getMode() == PrimitiveSet::POLYGON ? "POLYGON" : "Dunno" ) << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
78
src/osgPlugins/normals/Normals.h
Normal file
78
src/osgPlugins/normals/Normals.h
Normal file
@ -0,0 +1,78 @@
|
||||
#ifndef NORMALS_DEF
|
||||
#define NORMALS_DEF
|
||||
|
||||
//#define DEBUG 1
|
||||
#ifdef DEBUG
|
||||
#include <iostream>
|
||||
#endif
|
||||
|
||||
#include <stack>
|
||||
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/NodeVisitor>
|
||||
#include <osg/MatrixTransform>
|
||||
|
||||
class Normals: public osg::Geode
|
||||
{
|
||||
public:
|
||||
enum Mode {
|
||||
SurfaceNormals,
|
||||
VertexNormals
|
||||
};
|
||||
|
||||
Normals( osg::Node *node, float scale=1.0, Mode mode=SurfaceNormals );
|
||||
|
||||
private:
|
||||
|
||||
class MakeNormalsVisitor : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
MakeNormalsVisitor(float normalScale=1.0, Normals::Mode=Normals::SurfaceNormals );
|
||||
|
||||
void setMode( Mode mode ) { _mode = mode; }
|
||||
|
||||
virtual void apply(osg::MatrixTransform& tx);
|
||||
|
||||
virtual void apply( osg::Geode &geode );
|
||||
|
||||
osg::Vec3Array *getCoords() { return _local_coords.get(); }
|
||||
|
||||
|
||||
private:
|
||||
osg::ref_ptr<osg::Vec3Array> _local_coords;
|
||||
float _normal_scale;
|
||||
Mode _mode;
|
||||
osg::Matrix _mat;
|
||||
std::stack<osg::Matrix> _matStack;
|
||||
|
||||
|
||||
void _processPrimitive( unsigned int nv,
|
||||
osg::Vec3Array::iterator coords,
|
||||
osg::Vec3Array::iterator normals,
|
||||
osg::Geometry::AttributeBinding binding );
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
static void _printPrimitiveType( osg::PrimitiveSet *pset );
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
class SurfaceNormals: public Normals
|
||||
{
|
||||
public:
|
||||
SurfaceNormals( Node *node, float scale=1.0 ):
|
||||
Normals( node, scale, Normals::SurfaceNormals ) {}
|
||||
};
|
||||
|
||||
class VertexNormals: public Normals
|
||||
{
|
||||
public:
|
||||
VertexNormals( Node *node, float scale=1.0 ):
|
||||
Normals( node, scale, Normals::VertexNormals ) {}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
95
src/osgPlugins/normals/ReaderWriterNormals.cpp
Normal file
95
src/osgPlugins/normals/ReaderWriterNormals.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <math.h>
|
||||
#include <osg/Notify>
|
||||
#include <osg/Group>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osgDB/FileNameUtils>
|
||||
#include <osgDB/Registry>
|
||||
|
||||
#include "Normals.h"
|
||||
|
||||
class NormalsReader: public osgDB::ReaderWriter
|
||||
{
|
||||
public:
|
||||
NormalsReader() {}
|
||||
|
||||
virtual const char* className() { return "Normals Pseudo Loader"; }
|
||||
|
||||
virtual bool acceptsExtension(const std::string& extension) const
|
||||
{
|
||||
return osgDB::equalCaseInsensitive(extension,"normals");
|
||||
}
|
||||
|
||||
virtual ReadResult readObject(const std::string& fileName, const Options* opt) const
|
||||
{ return readNode(fileName,opt); }
|
||||
|
||||
virtual ReadResult readNode(const std::string& fileName, const Options* options) const
|
||||
{
|
||||
std::string ext = osgDB::getFileExtension(fileName);
|
||||
if (!acceptsExtension(ext))
|
||||
return ReadResult::FILE_NOT_HANDLED;
|
||||
|
||||
float scale = 1.0;
|
||||
Normals::Mode mode = Normals::VertexNormals;
|
||||
|
||||
if (options)
|
||||
{
|
||||
std::istringstream iss(options->getOptionString());
|
||||
std::string opt;
|
||||
while (iss >> opt)
|
||||
{
|
||||
if( opt == "help" || opt == "HELP" )
|
||||
{
|
||||
osg::notify( osg::INFO ) <<
|
||||
"Normals Plugin usage: <application> [-O options] <model.ext>.normals\n"
|
||||
" options: \"scale=<scale>\" (default = 1.0)\n"
|
||||
" \"mode=<VertexNormals|SurfaceNormals>\" (default = VertexNormals)" << std::endl;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
int index = opt.find( "=" );
|
||||
if( opt.substr( 0, index ) == "scale" ||
|
||||
opt.substr( 0, index ) == "SCALE" )
|
||||
{
|
||||
scale = atof( opt.substr( index+1 ).c_str() );
|
||||
}
|
||||
else if( opt.substr( 0, index ) == "mode" || opt.substr( 0, index ) == "MODE" )
|
||||
{
|
||||
std::string modestr = opt.substr(index+1);
|
||||
if( modestr == "VertexNormals" )
|
||||
mode = Normals::VertexNormals;
|
||||
else if( modestr == "SurfaceNormals" )
|
||||
mode = Normals::SurfaceNormals;
|
||||
else
|
||||
mode = Normals::VertexNormals;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string nodeName = osgDB::getNameLessExtension( fileName );
|
||||
if( !nodeName.empty() )
|
||||
{
|
||||
osg::ref_ptr<osg::Node> node = osgDB::readNodeFile( nodeName );
|
||||
if( node.valid() )
|
||||
{
|
||||
osg::ref_ptr<osg::Group> group = new osg::Group;
|
||||
group->addChild( node.get() );
|
||||
if( mode == Normals::VertexNormals )
|
||||
group->addChild( new VertexNormals( node.get(), scale ));
|
||||
else if( mode == Normals::SurfaceNormals )
|
||||
group->addChild( new SurfaceNormals( node.get(), scale ));
|
||||
|
||||
return group.get();
|
||||
}
|
||||
}
|
||||
return 0L;
|
||||
}
|
||||
};
|
||||
|
||||
osgDB::RegisterReaderWriterProxy<NormalsReader> g_normalsReader_Proxy;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user