161 lines
4.7 KiB
C++
161 lines
4.7 KiB
C++
// -*-c++-*-
|
|
|
|
/*
|
|
* Wavefront OBJ loader for Open Scene Graph
|
|
*
|
|
* Copyright (C) 2001 Ulrich Hertlein <u.hertlein@web.de>
|
|
*
|
|
* Modified by Robert Osfield to support per Drawable coord, normal and
|
|
* texture coord arrays, bug fixes, and support for texture mapping.
|
|
*
|
|
* Writing support added 2007 by Stephan Huber, http://digitalmind.de,
|
|
* some ideas taken from the dae-plugin
|
|
*
|
|
* The Open Scene Graph (OSG) is a cross platform C++/OpenGL library for
|
|
* real-time rendering of large 3D photo-realistic models.
|
|
* The OSG homepage is http://www.openscenegraph.org/
|
|
*/
|
|
|
|
#ifndef OBJ_WRITER_NODE_VISITOR_HEADER__
|
|
#define OBJ_WRITER_NODE_VISITOR_HEADER__
|
|
|
|
|
|
#include <string>
|
|
#include <stack>
|
|
#include <sstream>
|
|
|
|
#include <osg/Notify>
|
|
#include <osg/Node>
|
|
#include <osg/MatrixTransform>
|
|
#include <osg/Geode>
|
|
|
|
#include <osg/Geometry>
|
|
#include <osg/StateSet>
|
|
#include <osg/Material>
|
|
#include <osg/Texture2D>
|
|
#include <osg/TexGen>
|
|
#include <osg/TexMat>
|
|
|
|
#include <osgDB/Registry>
|
|
#include <osgDB/ReadFile>
|
|
#include <osgDB/FileUtils>
|
|
#include <osgDB/FileNameUtils>
|
|
|
|
|
|
|
|
|
|
#include <map>
|
|
#include <set>
|
|
|
|
class OBJWriterNodeVisitor: public osg::NodeVisitor {
|
|
|
|
public:
|
|
OBJWriterNodeVisitor(std::ostream& fout, const std::string materialFileName = "") :
|
|
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
|
_fout(fout),
|
|
_currentStateSet(new osg::StateSet()),
|
|
_lastVertexIndex(1),
|
|
_lastNormalIndex(1),
|
|
_lastTexIndex(1)
|
|
{
|
|
_fout << "# file written by OpenSceneGraph" << std::endl << std::endl;
|
|
|
|
if (!materialFileName.empty()) {
|
|
_fout << "mtllib " << materialFileName << std::endl << std::endl;
|
|
}
|
|
}
|
|
|
|
virtual void apply(osg::Geometry & geometry);
|
|
virtual void apply(osg::Geode & node);
|
|
|
|
virtual void apply(osg::Group & node)
|
|
{
|
|
pushStateSet(node.getStateSet());
|
|
_nameStack.push_back( node.getName().empty() ? node.className() : node.getName() );
|
|
|
|
_fout << std::endl;
|
|
_fout << "g " << getUniqueName() << std::endl;
|
|
|
|
traverse( node );
|
|
|
|
_nameStack.pop_back();
|
|
|
|
popStateSet(node.getStateSet());
|
|
}
|
|
|
|
void pushStateSet(osg::StateSet* ss)
|
|
{
|
|
if (NULL!=ss) {
|
|
// Save our current stateset
|
|
_stateSetStack.push(_currentStateSet.get());
|
|
|
|
// merge with node stateset
|
|
_currentStateSet = static_cast<osg::StateSet*>(_currentStateSet->clone(osg::CopyOp::SHALLOW_COPY));
|
|
_currentStateSet->merge(*ss);
|
|
}
|
|
}
|
|
|
|
|
|
void popStateSet(osg::StateSet* ss)
|
|
{
|
|
if (NULL!=ss) {
|
|
// restore the previous stateset
|
|
_currentStateSet = _stateSetStack.top();
|
|
_stateSetStack.pop();
|
|
}
|
|
}
|
|
|
|
|
|
void writeMaterials(std::ostream& fout);
|
|
|
|
|
|
|
|
class OBJMaterial {
|
|
public:
|
|
OBJMaterial() {}
|
|
OBJMaterial(osg::Material* mat, osg::Texture* tex);
|
|
|
|
osg::Vec4 diffuse, ambient, specular;
|
|
float shininess;
|
|
std::string image;
|
|
std::string name;
|
|
};
|
|
|
|
protected:
|
|
struct CompareStateSet
|
|
{
|
|
bool operator()(const osg::ref_ptr<osg::StateSet>& ss1, const osg::ref_ptr<osg::StateSet>& ss2) const
|
|
{
|
|
//std::cout << "CompareStateSet: " << ss1->compare(*ss2, false) << " " << ss1 << " " << ss2 << std::endl;
|
|
return ss1->compare(*ss2, true) < 0;
|
|
}
|
|
};
|
|
|
|
|
|
private:
|
|
|
|
OBJWriterNodeVisitor& operator = (const OBJWriterNodeVisitor&) { return *this; }
|
|
|
|
void processGeometry(osg::Geometry* geo, osg::Matrix& m);
|
|
void processArray(const std::string& key, osg::Array* array, const osg::Matrix& m = osg::Matrix::identity(), bool isNormal = false);
|
|
|
|
void processStateSet(osg::StateSet* stateset);
|
|
|
|
std::string getUniqueName(const std::string& defaultValue = "");
|
|
|
|
typedef std::stack<osg::ref_ptr<osg::StateSet> > StateSetStack;
|
|
typedef std::map< osg::ref_ptr<osg::StateSet>, OBJMaterial, CompareStateSet> MaterialMap;
|
|
|
|
|
|
std::ostream& _fout;
|
|
std::list<std::string> _nameStack;
|
|
StateSetStack _stateSetStack;
|
|
osg::ref_ptr<osg::StateSet> _currentStateSet;
|
|
std::map<std::string, unsigned int> _nameMap;
|
|
unsigned int _lastVertexIndex, _lastNormalIndex, _lastTexIndex;
|
|
MaterialMap _materialMap;
|
|
|
|
};
|
|
|
|
#endif
|