Files
OpenSceneGraph/src/osgPlugins/normals/ReaderWriterNormals.cpp
Robert Osfield dd996a3289 Introduced CMake option OSG_PROVIDE_READFILE option that defaults to ON, but when switched to OFF disables the building of the osgDB::read*File() methods,
forcing users to use osgDB::readRef*File() methods.  The later is preferable as it closes a potential threading bug when using paging databases in conjunction
with the osgDB::Registry Object Cache.  This threading bug occurs when one thread gets an object from the Cache via an osgDB::read*File() call where only
a pointer to the object is passed back, so taking a reference to the object is delayed till it gets reassigned to a ref_ptr<>, but at the same time another
thread calls a flush of the Object Cache deleting this object as it's referenceCount is now zero.  Using osgDB::readREf*File() makes sure the a ref_ptr<> is
passed back and the referenceCount never goes to zero.

To ensure the OSG builds when OSG_PROVIDE_READFILE is to OFF the many cases of osgDB::read*File() usage had to be replaced with a ref_ptr<> osgDB::readRef*File()
usage.  The avoid this change causing lots of other client code to be rewritten to handle the use of ref_ptr<> in place of C pointer I introduced a serious of
templte methods in various class to adapt ref_ptr<> to the underly C pointer to be passed to old OSG API's, example of this is found in include/osg/Group:

    bool addChild(Node* child); // old method which can only be used with a Node*

    tempalte<class T> bool addChild(const osg::ref_ptr<T>& child) { return addChild(child.get()); } // adapter template method

These changes together cover 149 modified files, so it's a large submission. This extent of changes are warrent to make use of the Object Cache
and multi-threaded loaded more robust.



git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk@15164 16af8721-9629-0410-8352-f15c8da7e697
2015-10-22 13:42:19 +00:00

110 lines
3.9 KiB
C++

#include <iostream>
#include <sstream>
#include <math.h>
#include <stdlib.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()
{
supportsExtension("normals","Normals Pseudo loader");
}
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" )
{
usage();
}
else
{
size_t index = opt.find( "=" );
if (index == std::string::npos) {
usage();
} else {
std::string key = opt.substr(0, index);
std::string value = opt.substr(index+1);
if( key == "scale" || key == "SCALE" )
{
scale = osg::asciiToFloat( value.c_str() );
}
else if( key == "mode" || key == "MODE" )
{
if( value == "VertexNormals" )
mode = Normals::VertexNormals;
else if( value == "SurfaceNormals" )
mode = Normals::SurfaceNormals;
else
mode = Normals::VertexNormals;
}
}
}
}
}
std::string nodeName = osgDB::getNameLessExtension( fileName );
if( !nodeName.empty() )
{
osg::ref_ptr<osg::Node> node = osgDB::readRefNodeFile( nodeName );
if( node.valid() )
{
osg::ref_ptr<osg::Group> group = new osg::Group;
group->addChild( node.get() );
const osg::BoundingSphere& bsph = group->getBound();
scale = bsph.radius() * 0.05f * scale; // default is 5% of bounding-sphere radius
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;
}
private:
void usage() const {
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;
}
};
REGISTER_OSGPLUGIN(normals, NormalsReader)