OpenSceneGraph/src/osgPlugins/osg/ReaderWriterOSG.cpp
Robert Osfield 1710b431a5 From Bryan Thrall, "The .osg plugin doesn't seem to support an option to write shader files
separately, so it always inlines them in the .osg file (as far as I can
tell). This change adds that ability. "
2009-02-09 21:48:30 +00:00

367 lines
12 KiB
C++

#include <sstream>
#include <osg/Image>
#include <osg/Group>
#include <osg/Notify>
#include <osgDB/FileNameUtils>
#include <osgDB/FileUtils>
#include <osgDB/fstream>
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>
using namespace osg;
using namespace osgDB;
// 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)
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");
}
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)