OpenSceneGraph/src/osgPlugins/osg/ReaderWriterOSG.cpp

385 lines
12 KiB
C++

#include <sstream>
#include <osg/Image>
#include <osg/Group>
#include <osg/Notify>
#include <osg/Version>
#include <osgDB/FileNameUtils>
#include <osgDB/FileUtils>
#include <osgDB/fstream>
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>
using namespace osg;
using namespace osgDB;
#if 0
// pull in symbols from individual .o's to enable the static build to work
USE_DOTOSGWRAPPER(AlphaFunc)
USE_DOTOSGWRAPPER(AnimationPath)
USE_DOTOSGWRAPPER(AutoTransform)
USE_DOTOSGWRAPPER(Billboard)
USE_DOTOSGWRAPPER(BlendColor)
USE_DOTOSGWRAPPER(BlendEquation)
USE_DOTOSGWRAPPER(BlendFunc)
USE_DOTOSGWRAPPER(Camera)
USE_DOTOSGWRAPPER(CameraView)
USE_DOTOSGWRAPPER(ClearNode)
USE_DOTOSGWRAPPER(ClipNode)
USE_DOTOSGWRAPPER(ClipPlane)
USE_DOTOSGWRAPPER(ClusterCullingCallback)
USE_DOTOSGWRAPPER(ColorMask)
USE_DOTOSGWRAPPER(ColorMatrix)
USE_DOTOSGWRAPPER(ConvexPlanarOccluder)
USE_DOTOSGWRAPPER(CoordinateSystemNode)
USE_DOTOSGWRAPPER(CullFace)
USE_DOTOSGWRAPPER(Depth)
USE_DOTOSGWRAPPER(Drawable)
USE_DOTOSGWRAPPER(EllipsoidModel)
USE_DOTOSGWRAPPER(Fog)
USE_DOTOSGWRAPPER(FragmentProgram)
USE_DOTOSGWRAPPER(FrontFace)
USE_DOTOSGWRAPPER(Geode)
USE_DOTOSGWRAPPER(Geometry)
USE_DOTOSGWRAPPER(Group)
USE_DOTOSGWRAPPER(Image)
USE_DOTOSGWRAPPER(ImageSequence)
USE_DOTOSGWRAPPER(Light)
USE_DOTOSGWRAPPER(LightModel)
USE_DOTOSGWRAPPER(LightSource)
USE_DOTOSGWRAPPER(LineStipple)
USE_DOTOSGWRAPPER(LineWidth)
USE_DOTOSGWRAPPER(LOD)
USE_DOTOSGWRAPPER(Material)
USE_DOTOSGWRAPPER(MatrixTransform)
USE_DOTOSGWRAPPER(NodeCallback)
USE_DOTOSGWRAPPER(Node)
USE_DOTOSGWRAPPER(Object)
USE_DOTOSGWRAPPER(OccluderNode)
USE_DOTOSGWRAPPER(OcclusionQueryNode)
USE_DOTOSGWRAPPER(PagedLOD)
USE_DOTOSGWRAPPER(Point)
USE_DOTOSGWRAPPER(PointSprite)
USE_DOTOSGWRAPPER(PolygonMode)
USE_DOTOSGWRAPPER(PolygonOffset)
USE_DOTOSGWRAPPER(PositionAttitudeTransform)
USE_DOTOSGWRAPPER(Program)
USE_DOTOSGWRAPPER(Projection)
USE_DOTOSGWRAPPER(ProxyNode)
USE_DOTOSGWRAPPER(Scissor)
USE_DOTOSGWRAPPER(Sequence)
USE_DOTOSGWRAPPER(ShadeModel)
USE_DOTOSGWRAPPER(Shader)
USE_DOTOSGWRAPPER(Sphere)
USE_DOTOSGWRAPPER(Cone)
USE_DOTOSGWRAPPER(Capsule)
USE_DOTOSGWRAPPER(Box)
USE_DOTOSGWRAPPER(HeightField)
USE_DOTOSGWRAPPER(CompositeShape)
USE_DOTOSGWRAPPER(Cylinder)
USE_DOTOSGWRAPPER(ShapeDrawable)
USE_DOTOSGWRAPPER(StateAttribute)
USE_DOTOSGWRAPPER(StateSet)
USE_DOTOSGWRAPPER(Stencil)
USE_DOTOSGWRAPPER(Switch)
USE_DOTOSGWRAPPER(TessellationHints)
USE_DOTOSGWRAPPER(TexEnvCombine)
USE_DOTOSGWRAPPER(TexEnv)
USE_DOTOSGWRAPPER(TexEnvFilter)
USE_DOTOSGWRAPPER(TexGen)
USE_DOTOSGWRAPPER(TexGenNode)
USE_DOTOSGWRAPPER(TexMat)
USE_DOTOSGWRAPPER(Texture1D)
USE_DOTOSGWRAPPER(Texture2D)
USE_DOTOSGWRAPPER(Texture3D)
USE_DOTOSGWRAPPER(Texture)
USE_DOTOSGWRAPPER(TextureCubeMap)
USE_DOTOSGWRAPPER(TextureRectangle)
USE_DOTOSGWRAPPER(Transform)
USE_DOTOSGWRAPPER(Uniform)
USE_DOTOSGWRAPPER(VertexProgram)
USE_DOTOSGWRAPPER(Viewport)
#endif
class OSGReaderWriter : public ReaderWriter
{
public:
OSGReaderWriter()
{
supportsExtension("osg","OpenSceneGraph Ascii file format");
supportsExtension("osgs","Psuedo OpenSceneGraph file loaded, with file encoded in filename string");
supportsOption("precision","Set the floating point precision when writing out files");
supportsOption("OutputTextureFiles","Write out the texture images to file");
supportsOption("includeExternalReferences","Export option");
supportsOption("writeExternalReferenceFiles","Export option");
std::string filename = osgDB::Registry::instance()->createLibraryNameForExtension("deprecated_osg");
if (osgDB::Registry::instance()->loadLibrary(filename)==osgDB::Registry::LOADED)
{
osg::notify(osg::NOTICE)<<"Constructor OSGReaderWriter - loaded OK"<<std::endl;
}
else
{
osg::notify(osg::NOTICE)<<"Constructor OSGReaderWriter - failed to load"<<std::endl;
}
}
virtual const char* className() const { return "OSG Reader/Writer"; }
virtual ReadResult readObject(const std::string& file, const Options* opt) const
{
std::string ext = osgDB::getLowerCaseFileExtension(file);
if (equalCaseInsensitive(ext,"osgs"))
{
std::istringstream fin(osgDB::getNameLessExtension(file));
if (fin) return readNode(fin,opt);
return ReadResult::ERROR_IN_READING_FILE;
}
if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
std::string fileName = osgDB::findDataFile( file, opt );
if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
// code for setting up the database path so that internally referenced file are searched for on relative paths.
osg::ref_ptr<Options> local_opt = opt ? static_cast<Options*>(opt->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileName));
osgDB::ifstream fin(fileName.c_str());
if (fin)
{
return readObject(fin, local_opt.get());
}
return 0L;
}
virtual ReadResult readObject(std::istream& fin, const Options* options) const
{
fin.imbue(std::locale::classic());
Input fr;
fr.attach(&fin);
fr.setOptions(options);
typedef std::vector<osg::Object*> ObjectList;
ObjectList objectList;
// load all nodes in file, placing them in a group.
while(!fr.eof())
{
Object *object = fr.readObject();
if (object) objectList.push_back(object);
else fr.advanceOverCurrentFieldOrBlock();
}
if (objectList.empty())
{
return ReadResult("No data loaded");
}
else if (objectList.size()==1)
{
return objectList.front();
}
else
{
return objectList.front();
}
}
virtual ReadResult readNode(const std::string& file, const Options* opt) const
{
std::string ext = osgDB::getLowerCaseFileExtension(file);
if (equalCaseInsensitive(ext,"osgs"))
{
std::istringstream fin(osgDB::getNameLessExtension(file));
if (fin) return readNode(fin,opt);
return ReadResult::ERROR_IN_READING_FILE;
}
if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
std::string fileName = osgDB::findDataFile( file, opt );
if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
// code for setting up the database path so that internally referenced file are searched for on relative paths.
osg::ref_ptr<Options> local_opt = opt ? static_cast<Options*>(opt->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileName));
osgDB::ifstream fin(fileName.c_str());
if (fin)
{
return readNode(fin, local_opt.get());
}
return 0L;
}
virtual ReadResult readNode(std::istream& fin, const Options* options) const
{
fin.imbue(std::locale::classic());
Input fr;
fr.attach(&fin);
fr.setOptions(options);
typedef std::vector<osg::Node*> NodeList;
NodeList nodeList;
// load all nodes in file, placing them in a group.
while(!fr.eof())
{
Node *node = fr.readNode();
if (node) nodeList.push_back(node);
else fr.advanceOverCurrentFieldOrBlock();
}
if (nodeList.empty())
{
return ReadResult("No data loaded");
}
else if (nodeList.size()==1)
{
return nodeList.front();
}
else
{
Group* group = new Group;
group->setName("import group");
for(NodeList::iterator itr=nodeList.begin();
itr!=nodeList.end();
++itr)
{
group->addChild(*itr);
}
return group;
}
}
void setPrecision(Output& fout, const osgDB::ReaderWriter::Options* options) const
{
if (options)
{
std::istringstream iss(options->getOptionString());
std::string opt;
while (iss >> opt)
{
if(opt=="PRECISION" || opt=="precision")
{
int prec;
iss >> prec;
fout.precision(prec);
}
if (opt=="OutputTextureFiles")
{
fout.setOutputTextureFiles(true);
}
if (opt=="OutputShaderFiles")
{
fout.setOutputShaderFiles(true);
}
}
}
}
virtual WriteResult writeObject(const Object& obj, const std::string& fileName, const osgDB::ReaderWriter::Options* options) const
{
std::string ext = osgDB::getLowerCaseFileExtension(fileName);
if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;
Output fout(fileName.c_str());
if (fout)
{
fout.setOptions(options);
setPrecision(fout,options);
fout.imbue(std::locale::classic());
fout.writeObject(obj);
fout.close();
return WriteResult::FILE_SAVED;
}
return WriteResult("Unable to open file for output");
}
virtual WriteResult writeObject(const Object& obj,std::ostream& fout, const osgDB::ReaderWriter::Options* options) const
{
if (fout)
{
Output foutput;
foutput.setOptions(options);
std::ios &fios = foutput;
fios.rdbuf(fout.rdbuf());
fout.imbue(std::locale::classic());
setPrecision(foutput,options);
foutput.writeObject(obj);
return WriteResult::FILE_SAVED;
}
return WriteResult("Unable to write to output stream");
}
virtual WriteResult writeNode(const Node& node, const std::string& fileName, const osgDB::ReaderWriter::Options* options) const
{
std::string ext = getFileExtension(fileName);
if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;
Output fout(fileName.c_str());
if (fout)
{
fout.setOptions(options);
fout.imbue(std::locale::classic());
setPrecision(fout,options);
fout.writeObject(node);
fout.close();
return WriteResult::FILE_SAVED;
}
return WriteResult("Unable to open file for output");
}
virtual WriteResult writeNode(const Node& node, std::ostream& fout, const osgDB::ReaderWriter::Options* options) const
{
if (fout)
{
Output foutput;
foutput.setOptions(options);
std::ios &fios = foutput;
fios.rdbuf(fout.rdbuf());
foutput.imbue(std::locale::classic());
setPrecision(foutput,options);
foutput.writeObject(node);
return WriteResult::FILE_SAVED;
}
return WriteResult("Unable to write to output stream");
}
};
// now register with Registry to instantiate the above
// reader/writer.
REGISTER_OSGPLUGIN(osg, OSGReaderWriter)