Ran script to remove trailing spaces and tabs
This commit is contained in:
@@ -8,66 +8,66 @@
|
||||
* 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,
|
||||
* 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 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/
|
||||
*/
|
||||
|
||||
#include <osg/io_utils>
|
||||
#include "OBJWriterNodeVisitor.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/** writes all values of an array out to a stream, applies a matrix beforehand if necessary */
|
||||
class ValueVisitor : public osg::ValueVisitor {
|
||||
public:
|
||||
ValueVisitor(std::ostream& fout, const osg::Matrix& m = osg::Matrix::identity(), bool isNormal = false) :
|
||||
osg::ValueVisitor(),
|
||||
_fout(fout),
|
||||
_m(m),
|
||||
ValueVisitor(std::ostream& fout, const osg::Matrix& m = osg::Matrix::identity(), bool isNormal = false) :
|
||||
osg::ValueVisitor(),
|
||||
_fout(fout),
|
||||
_m(m),
|
||||
_isNormal(isNormal)
|
||||
{
|
||||
{
|
||||
_applyMatrix = (_m != osg::Matrix::identity());
|
||||
if (_isNormal) _origin = osg::Vec3(0,0,0) * _m;
|
||||
}
|
||||
|
||||
virtual void apply (osg::Vec2 & inv)
|
||||
{
|
||||
_fout << inv[0] << ' ' << inv[1];
|
||||
|
||||
virtual void apply (osg::Vec2 & inv)
|
||||
{
|
||||
_fout << inv[0] << ' ' << inv[1];
|
||||
}
|
||||
|
||||
virtual void apply (osg::Vec3 & inv)
|
||||
{
|
||||
|
||||
virtual void apply (osg::Vec3 & inv)
|
||||
{
|
||||
osg::Vec3 v(inv);
|
||||
if (_applyMatrix) v = (_isNormal) ? (v * _m) - _origin : v * _m;
|
||||
_fout << v[0] << ' ' << v[1] << ' ' << v[2];
|
||||
_fout << v[0] << ' ' << v[1] << ' ' << v[2];
|
||||
}
|
||||
|
||||
|
||||
virtual void apply (osg::Vec2b & inv)
|
||||
{
|
||||
_fout << inv[0] << ' ' << inv[1];
|
||||
{
|
||||
_fout << inv[0] << ' ' << inv[1];
|
||||
}
|
||||
|
||||
virtual void apply (osg::Vec3b & inv)
|
||||
{
|
||||
|
||||
virtual void apply (osg::Vec3b & inv)
|
||||
{
|
||||
osg::Vec3 v(inv[0], inv[1], inv[2]);
|
||||
if (_applyMatrix) v = (_isNormal) ? (v * _m) - _origin : v * _m;
|
||||
_fout << v[0] << ' ' << v[1] << ' ' << v[2];
|
||||
_fout << v[0] << ' ' << v[1] << ' ' << v[2];
|
||||
}
|
||||
|
||||
virtual void apply (osg::Vec2s & inv)
|
||||
{
|
||||
_fout << inv[0] << ' ' << inv[1];
|
||||
|
||||
virtual void apply (osg::Vec2s & inv)
|
||||
{
|
||||
_fout << inv[0] << ' ' << inv[1];
|
||||
}
|
||||
|
||||
virtual void apply (osg::Vec3s & inv)
|
||||
{
|
||||
|
||||
virtual void apply (osg::Vec3s & inv)
|
||||
{
|
||||
osg::Vec3 v(inv[0], inv[1], inv[2]);
|
||||
if (_applyMatrix) v = (_isNormal) ? (v * _m) - _origin : v * _m;
|
||||
_fout << v[0] << ' ' << v[1] << ' ' << v[2];
|
||||
_fout << v[0] << ' ' << v[1] << ' ' << v[2];
|
||||
}
|
||||
private:
|
||||
|
||||
@@ -81,10 +81,10 @@ class ValueVisitor : public osg::ValueVisitor {
|
||||
|
||||
/** writes all primitives of a primitive-set out to a stream, decomposes quads to triangles, line-strips to lines etc */
|
||||
class ObjPrimitiveIndexWriter : public osg::PrimitiveIndexFunctor {
|
||||
|
||||
|
||||
public:
|
||||
ObjPrimitiveIndexWriter(std::ostream& fout,osg::Geometry* geo, unsigned int normalIndex, unsigned int lastVertexIndex, unsigned int lastNormalIndex, unsigned int lastTexIndex) :
|
||||
osg::PrimitiveIndexFunctor(),
|
||||
ObjPrimitiveIndexWriter(std::ostream& fout,osg::Geometry* geo, unsigned int normalIndex, unsigned int lastVertexIndex, unsigned int lastNormalIndex, unsigned int lastTexIndex) :
|
||||
osg::PrimitiveIndexFunctor(),
|
||||
_fout(fout),
|
||||
_lastVertexIndex(lastVertexIndex),
|
||||
_lastNormalIndex(lastNormalIndex),
|
||||
@@ -95,29 +95,29 @@ class ObjPrimitiveIndexWriter : public osg::PrimitiveIndexFunctor {
|
||||
_normalIndex(normalIndex)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual void setVertexArray(unsigned int,const osg::Vec2*) {}
|
||||
|
||||
virtual void setVertexArray(unsigned int ,const osg::Vec3* ) {}
|
||||
|
||||
virtual void setVertexArray(unsigned int,const osg::Vec4* ) {}
|
||||
|
||||
|
||||
virtual void setVertexArray(unsigned int,const osg::Vec2d*) {}
|
||||
|
||||
virtual void setVertexArray(unsigned int ,const osg::Vec3d* ) {}
|
||||
|
||||
virtual void setVertexArray(unsigned int,const osg::Vec4d* ) {}
|
||||
|
||||
void write(unsigned int i)
|
||||
|
||||
void write(unsigned int i)
|
||||
{
|
||||
_fout << (i + _lastVertexIndex) << "/";
|
||||
|
||||
if (_hasTexCoords || _hasNormalCoords)
|
||||
|
||||
if (_hasTexCoords || _hasNormalCoords)
|
||||
{
|
||||
if (_hasTexCoords)
|
||||
_fout << (i + _lastTexIndex);
|
||||
_fout << "/";
|
||||
if (_hasNormalCoords)
|
||||
if (_hasNormalCoords)
|
||||
{
|
||||
if (_geo->getNormalBinding() == osg::Geometry::BIND_PER_VERTEX)
|
||||
_fout << (i+_lastNormalIndex);
|
||||
@@ -127,7 +127,7 @@ class ObjPrimitiveIndexWriter : public osg::PrimitiveIndexFunctor {
|
||||
}
|
||||
_fout << " ";
|
||||
}
|
||||
|
||||
|
||||
// operator for triangles
|
||||
void writeTriangle(unsigned int i1, unsigned int i2, unsigned int i3)
|
||||
{
|
||||
@@ -139,9 +139,9 @@ class ObjPrimitiveIndexWriter : public osg::PrimitiveIndexFunctor {
|
||||
// not sure if this is correct?
|
||||
if(_geo->getNormalBinding() && _geo->getNormalBinding() == osg::Geometry::BIND_PER_PRIMITIVE) ++_normalIndex;
|
||||
}
|
||||
|
||||
|
||||
// operator for lines
|
||||
void writeLine(unsigned int i1, unsigned int i2)
|
||||
void writeLine(unsigned int i1, unsigned int i2)
|
||||
{
|
||||
_fout << "l ";
|
||||
write(i1);
|
||||
@@ -150,9 +150,9 @@ class ObjPrimitiveIndexWriter : public osg::PrimitiveIndexFunctor {
|
||||
// not sure if this is correct?
|
||||
if(_geo->getNormalBinding() && _geo->getNormalBinding() == osg::Geometry::BIND_PER_PRIMITIVE) ++_normalIndex;
|
||||
}
|
||||
|
||||
|
||||
// operator for points
|
||||
void writePoint(unsigned int i1)
|
||||
void writePoint(unsigned int i1)
|
||||
{
|
||||
_fout << "p ";
|
||||
write(i1);
|
||||
@@ -180,8 +180,8 @@ class ObjPrimitiveIndexWriter : public osg::PrimitiveIndexFunctor {
|
||||
}
|
||||
}
|
||||
|
||||
virtual void drawArrays(GLenum mode,GLint first,GLsizei count);
|
||||
|
||||
virtual void drawArrays(GLenum mode,GLint first,GLsizei count);
|
||||
|
||||
virtual void drawElements(GLenum mode,GLsizei count,const GLubyte* indices)
|
||||
{
|
||||
drawElementsImplementation<GLubyte>(mode, count, indices);
|
||||
@@ -189,21 +189,21 @@ class ObjPrimitiveIndexWriter : public osg::PrimitiveIndexFunctor {
|
||||
virtual void drawElements(GLenum mode,GLsizei count,const GLushort* indices)
|
||||
{
|
||||
drawElementsImplementation<GLushort>(mode, count, indices);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void drawElements(GLenum mode,GLsizei count,const GLuint* indices)
|
||||
{
|
||||
drawElementsImplementation<GLuint>(mode, count, indices);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
template<typename T>void drawElementsImplementation(GLenum mode, GLsizei count, const T* indices)
|
||||
|
||||
template<typename T>void drawElementsImplementation(GLenum mode, GLsizei count, const T* indices)
|
||||
{
|
||||
if (indices==0 || count==0) return;
|
||||
|
||||
typedef const T* IndexPointer;
|
||||
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case(GL_TRIANGLES):
|
||||
@@ -211,7 +211,7 @@ class ObjPrimitiveIndexWriter : public osg::PrimitiveIndexFunctor {
|
||||
IndexPointer ilast = &indices[count];
|
||||
for(IndexPointer iptr=indices;iptr<ilast;iptr+=3)
|
||||
writeTriangle(*iptr,*(iptr+1),*(iptr+2));
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case(GL_TRIANGLE_STRIP):
|
||||
@@ -260,7 +260,7 @@ class ObjPrimitiveIndexWriter : public osg::PrimitiveIndexFunctor {
|
||||
{
|
||||
IndexPointer ilast = &indices[count];
|
||||
for(IndexPointer iptr=indices;iptr<ilast;++iptr)
|
||||
|
||||
|
||||
{
|
||||
writePoint(*iptr);
|
||||
}
|
||||
@@ -278,7 +278,7 @@ class ObjPrimitiveIndexWriter : public osg::PrimitiveIndexFunctor {
|
||||
}
|
||||
case(GL_LINE_STRIP):
|
||||
{
|
||||
|
||||
|
||||
IndexPointer ilast = &indices[count];
|
||||
for(IndexPointer iptr=indices+1;iptr<ilast;iptr+=2)
|
||||
|
||||
@@ -302,8 +302,8 @@ class ObjPrimitiveIndexWriter : public osg::PrimitiveIndexFunctor {
|
||||
// uhm should never come to this point :)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
ObjPrimitiveIndexWriter& operator = (const ObjPrimitiveIndexWriter&) { return *this; }
|
||||
@@ -373,7 +373,7 @@ void ObjPrimitiveIndexWriter::drawArrays(GLenum mode,GLint first,GLsizei count)
|
||||
}
|
||||
case(GL_POINTS):
|
||||
{
|
||||
|
||||
|
||||
for(GLsizei i=0;i<count;++i)
|
||||
{
|
||||
writePoint(i);
|
||||
@@ -407,11 +407,11 @@ void ObjPrimitiveIndexWriter::drawArrays(GLenum mode,GLint first,GLsizei count)
|
||||
break;
|
||||
}
|
||||
default:
|
||||
OSG_WARN << "OBJWriterNodeVisitor :: can't handle mode " << mode << std::endl;
|
||||
OSG_WARN << "OBJWriterNodeVisitor :: can't handle mode " << mode << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
OBJWriterNodeVisitor::OBJMaterial::OBJMaterial(osg::Material* mat, osg::Texture* tex) :
|
||||
diffuse(1,1,1,1),
|
||||
@@ -421,40 +421,40 @@ OBJWriterNodeVisitor::OBJMaterial::OBJMaterial(osg::Material* mat, osg::Texture*
|
||||
{
|
||||
static unsigned int s_objmaterial_id = 0;
|
||||
++s_objmaterial_id;
|
||||
std::stringstream ss;
|
||||
std::stringstream ss;
|
||||
ss << "material_" << s_objmaterial_id;
|
||||
name = ss.str();
|
||||
|
||||
|
||||
if (mat) {
|
||||
diffuse = mat->getDiffuse(osg::Material::FRONT);
|
||||
ambient = mat->getAmbient(osg::Material::FRONT);
|
||||
specular = mat->getSpecular(osg::Material::FRONT);
|
||||
}
|
||||
|
||||
|
||||
if (tex) {
|
||||
osg::Image* img = tex->getImage(0);
|
||||
if ((img) && (!img->getFileName().empty()))
|
||||
image = img->getFileName();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& fout, const OBJWriterNodeVisitor::OBJMaterial& mat) {
|
||||
|
||||
|
||||
fout << "newmtl " << mat.name << std::endl;
|
||||
fout << " " << "Ka " << mat.ambient << std::endl;
|
||||
fout << " " << "Kd " << mat.diffuse << std::endl;
|
||||
fout << " " << "Ks " << mat.specular << std::endl;
|
||||
|
||||
|
||||
if(!mat.image.empty())
|
||||
fout << " " << "map_Kd " << mat.image << std::endl;
|
||||
|
||||
|
||||
return fout;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void OBJWriterNodeVisitor::writeMaterials(std::ostream& fout)
|
||||
void OBJWriterNodeVisitor::writeMaterials(std::ostream& fout)
|
||||
{
|
||||
for(MaterialMap::iterator i = _materialMap.begin(); i != _materialMap.end(); ++i)
|
||||
{
|
||||
@@ -464,19 +464,19 @@ void OBJWriterNodeVisitor::writeMaterials(std::ostream& fout)
|
||||
|
||||
|
||||
std::string OBJWriterNodeVisitor::getUniqueName(const std::string& defaultvalue) {
|
||||
|
||||
|
||||
std::string name = "";
|
||||
for(std::list<std::string>::iterator i = _nameStack.begin(); i != _nameStack.end(); ++i) {
|
||||
if (!name.empty()) name+="_";
|
||||
name += (*i);
|
||||
}
|
||||
|
||||
|
||||
if (!defaultvalue.empty())
|
||||
name += "_" +defaultvalue;
|
||||
|
||||
|
||||
if (_nameMap.find(name) == _nameMap.end())
|
||||
_nameMap.insert(std::make_pair(name, 0u));
|
||||
|
||||
|
||||
std::stringstream ss;
|
||||
ss << name << "_" << _nameMap[name];
|
||||
++(_nameMap[name]);
|
||||
@@ -488,7 +488,7 @@ void OBJWriterNodeVisitor::processArray(const std::string& key, osg::Array* arra
|
||||
{
|
||||
if (array == NULL)
|
||||
return;
|
||||
|
||||
|
||||
ValueVisitor vv(_fout, m, isNormal);
|
||||
_fout << std::endl;
|
||||
for(unsigned int i = 0; i < array->getNumElements(); ++i) {
|
||||
@@ -496,57 +496,57 @@ void OBJWriterNodeVisitor::processArray(const std::string& key, osg::Array* arra
|
||||
array->accept(i, vv);
|
||||
_fout << std::endl;
|
||||
}
|
||||
|
||||
|
||||
_fout << "# " << array->getNumElements() << " elements written" << std::endl;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void OBJWriterNodeVisitor::processStateSet(osg::StateSet* ss)
|
||||
void OBJWriterNodeVisitor::processStateSet(osg::StateSet* ss)
|
||||
{
|
||||
if (_materialMap.find(ss) != _materialMap.end()) {
|
||||
_fout << "usemtl " << _materialMap[ss].name << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
osg::Material* mat = dynamic_cast<osg::Material*>(ss->getAttribute(osg::StateAttribute::MATERIAL));
|
||||
osg::Texture* tex = dynamic_cast<osg::Texture*>(ss->getTextureAttribute(0, osg::StateAttribute::TEXTURE));
|
||||
|
||||
if (mat || tex)
|
||||
|
||||
if (mat || tex)
|
||||
{
|
||||
_materialMap.insert(std::make_pair(osg::ref_ptr<osg::StateSet>(ss), OBJMaterial(mat, tex)));
|
||||
_fout << "usemtl " << _materialMap[ss].name << std::endl;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void OBJWriterNodeVisitor::processGeometry(osg::Geometry* geo, osg::Matrix& m) {
|
||||
_fout << std::endl;
|
||||
_fout << "o " << getUniqueName( geo->getName().empty() ? geo->className() : geo->getName() ) << std::endl;
|
||||
|
||||
|
||||
processStateSet(_currentStateSet.get());
|
||||
|
||||
|
||||
processArray("v", geo->getVertexArray(), m, false);
|
||||
processArray("vn", geo->getNormalArray(), m, true);
|
||||
processArray("vt", geo->getTexCoordArray(0)); // we support only tex-unit 0
|
||||
unsigned int normalIndex = 0;
|
||||
for(unsigned int i = 0; i < geo->getNumPrimitiveSets(); ++i)
|
||||
for(unsigned int i = 0; i < geo->getNumPrimitiveSets(); ++i)
|
||||
{
|
||||
osg::PrimitiveSet* ps = geo->getPrimitiveSet(i);
|
||||
|
||||
|
||||
ObjPrimitiveIndexWriter pif(_fout, geo, normalIndex, _lastVertexIndex, _lastNormalIndex, _lastTexIndex);
|
||||
ps->accept(pif);
|
||||
|
||||
|
||||
if(geo->getNormalArray() && geo->getNormalBinding() == osg::Geometry::BIND_PER_PRIMITIVE_SET)
|
||||
++normalIndex;
|
||||
}
|
||||
if (geo->getVertexArray())
|
||||
if (geo->getVertexArray())
|
||||
_lastVertexIndex += geo->getVertexArray()->getNumElements();
|
||||
if (geo->getNormalArray())
|
||||
_lastNormalIndex += geo->getNormalArray()->getNumElements();
|
||||
if(geo->getTexCoordArray(0))
|
||||
_lastTexIndex += geo->getTexCoordArray(0)->getNumElements();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void OBJWriterNodeVisitor::apply( osg::Geode &node )
|
||||
@@ -562,9 +562,9 @@ void OBJWriterNodeVisitor::apply( osg::Geode &node )
|
||||
if ( g != NULL )
|
||||
{
|
||||
pushStateSet(g->getStateSet());
|
||||
|
||||
|
||||
processGeometry(g,m);
|
||||
|
||||
|
||||
popStateSet(g->getStateSet());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,14 +8,14 @@
|
||||
* 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,
|
||||
* 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 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__
|
||||
|
||||
@@ -50,33 +50,33 @@
|
||||
class OBJWriterNodeVisitor: public osg::NodeVisitor {
|
||||
|
||||
public:
|
||||
OBJWriterNodeVisitor(std::ostream& fout, const std::string materialFileName = "") :
|
||||
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
||||
_fout(fout),
|
||||
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::Geode &node);
|
||||
|
||||
virtual void apply(osg::Group &node)
|
||||
|
||||
virtual void apply(osg::Group &node)
|
||||
{
|
||||
_nameStack.push_back( node.getName().empty() ? node.className() : node.getName() );
|
||||
_fout << std::endl;
|
||||
_fout << "g " << getUniqueName() << std::endl;
|
||||
|
||||
|
||||
osg::NodeVisitor::traverse( node );
|
||||
_nameStack.pop_back();
|
||||
}
|
||||
|
||||
|
||||
void traverse (osg::Node &node)
|
||||
{
|
||||
pushStateSet(node.getStateSet());
|
||||
@@ -91,10 +91,10 @@ class OBJWriterNodeVisitor: public osg::NodeVisitor {
|
||||
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);
|
||||
_currentStateSet->merge(*ss);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,22 +107,22 @@ class OBJWriterNodeVisitor: public osg::NodeVisitor {
|
||||
_stateSetStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void writeMaterials(std::ostream& fout);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class OBJMaterial {
|
||||
public:
|
||||
OBJMaterial() {}
|
||||
OBJMaterial(osg::Material* mat, osg::Texture* tex);
|
||||
|
||||
|
||||
osg::Vec4 diffuse, ambient, specular;
|
||||
std::string image;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
|
||||
protected:
|
||||
struct CompareStateSet
|
||||
{
|
||||
@@ -133,18 +133,18 @@ class OBJWriterNodeVisitor: public osg::NodeVisitor {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
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;
|
||||
|
||||
@@ -155,7 +155,7 @@ class OBJWriterNodeVisitor: public osg::NodeVisitor {
|
||||
osg::ref_ptr<osg::StateSet> _currentStateSet;
|
||||
std::map<std::string, unsigned int> _nameMap;
|
||||
unsigned int _lastVertexIndex, _lastNormalIndex, _lastTexIndex;
|
||||
MaterialMap _materialMap;
|
||||
MaterialMap _materialMap;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
* 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,
|
||||
* 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 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/
|
||||
*/
|
||||
|
||||
@@ -78,54 +78,54 @@ public:
|
||||
virtual ReadResult readNode(const std::string& fileName, const osgDB::ReaderWriter::Options* options) const;
|
||||
|
||||
virtual ReadResult readNode(std::istream& fin, const Options* options) const;
|
||||
|
||||
virtual WriteResult writeObject(const osg::Object& obj,const std::string& fileName,const Options* options=NULL) const
|
||||
|
||||
virtual WriteResult writeObject(const osg::Object& obj,const std::string& fileName,const Options* options=NULL) const
|
||||
{
|
||||
const osg::Node* node = dynamic_cast<const osg::Node*>(&obj);
|
||||
if (node)
|
||||
return writeNode(*node, fileName, options);
|
||||
else
|
||||
return WriteResult(WriteResult::FILE_NOT_HANDLED);
|
||||
else
|
||||
return WriteResult(WriteResult::FILE_NOT_HANDLED);
|
||||
}
|
||||
|
||||
virtual WriteResult writeNode(const osg::Node& node,const std::string& fileName,const Options* options =NULL) const
|
||||
{
|
||||
|
||||
virtual WriteResult writeNode(const osg::Node& node,const std::string& fileName,const Options* options =NULL) const
|
||||
{
|
||||
if (!acceptsExtension(osgDB::getFileExtension(fileName)))
|
||||
return WriteResult(WriteResult::FILE_NOT_HANDLED);
|
||||
|
||||
return WriteResult(WriteResult::FILE_NOT_HANDLED);
|
||||
|
||||
osgDB::ofstream f(fileName.c_str());
|
||||
std::string materialFile = osgDB::getNameLessExtension(fileName) + ".mtl";
|
||||
OBJWriterNodeVisitor nv(f, osgDB::getSimpleFileName(materialFile));
|
||||
|
||||
|
||||
// we must cast away constness
|
||||
(const_cast<osg::Node*>(&node))->accept(nv);
|
||||
|
||||
|
||||
osgDB::ofstream mf(materialFile.c_str());
|
||||
nv.writeMaterials(mf);
|
||||
|
||||
return WriteResult(WriteResult::FILE_SAVED);
|
||||
|
||||
return WriteResult(WriteResult::FILE_SAVED);
|
||||
}
|
||||
|
||||
|
||||
virtual WriteResult writeObject(const osg::Object& obj,std::ostream& fout,const Options* options=NULL) const
|
||||
|
||||
virtual WriteResult writeObject(const osg::Object& obj,std::ostream& fout,const Options* options=NULL) const
|
||||
{
|
||||
const osg::Node* node = dynamic_cast<const osg::Node*>(&obj);
|
||||
if (node)
|
||||
return writeNode(*node, fout, options);
|
||||
else
|
||||
return WriteResult(WriteResult::FILE_NOT_HANDLED);
|
||||
else
|
||||
return WriteResult(WriteResult::FILE_NOT_HANDLED);
|
||||
}
|
||||
|
||||
virtual WriteResult writeNode(const osg::Node& node,std::ostream& fout,const Options* =NULL) const
|
||||
{
|
||||
virtual WriteResult writeNode(const osg::Node& node,std::ostream& fout,const Options* =NULL) const
|
||||
{
|
||||
// writing to a stream does not support materials
|
||||
|
||||
|
||||
OBJWriterNodeVisitor nv(fout);
|
||||
|
||||
|
||||
// we must cast away constness
|
||||
(const_cast<osg::Node*>(&node))->accept(nv);
|
||||
|
||||
return WriteResult(WriteResult::FILE_SAVED);
|
||||
|
||||
return WriteResult(WriteResult::FILE_SAVED);
|
||||
}
|
||||
|
||||
|
||||
@@ -145,16 +145,16 @@ protected:
|
||||
};
|
||||
|
||||
typedef std::map< std::string, osg::ref_ptr<osg::StateSet> > MaterialToStateSetMap;
|
||||
|
||||
|
||||
void buildMaterialToStateSetMap(obj::Model& model, MaterialToStateSetMap& materialToSetSetMapObj, ObjOptionsStruct& localOptions, const Options* options) const;
|
||||
|
||||
|
||||
osg::Geometry* convertElementListToGeometry(obj::Model& model, obj::Model::ElementList& elementList, ObjOptionsStruct& localOptions) const;
|
||||
|
||||
|
||||
osg::Node* convertModelToSceneGraph(obj::Model& model, ObjOptionsStruct& localOptions, const Options* options) const;
|
||||
|
||||
inline osg::Vec3 transformVertex(const osg::Vec3& vec, const bool rotate) const ;
|
||||
inline osg::Vec3 transformNormal(const osg::Vec3& vec, const bool rotate) const ;
|
||||
|
||||
|
||||
ObjOptionsStruct parseOptions(const Options* options) const;
|
||||
|
||||
|
||||
@@ -198,12 +198,12 @@ static void load_material_texture( obj::Model &model,
|
||||
if (!filename.empty())
|
||||
{
|
||||
osg::ref_ptr< osg::Image > image;
|
||||
if ( !model.getDatabasePath().empty() )
|
||||
if ( !model.getDatabasePath().empty() )
|
||||
{
|
||||
// first try with database path of parent.
|
||||
// first try with database path of parent.
|
||||
image = osgDB::readRefImageFile(model.getDatabasePath()+'/'+filename, options);
|
||||
}
|
||||
|
||||
|
||||
if ( !image.valid() )
|
||||
{
|
||||
// if not already set then try the filename as is.
|
||||
@@ -230,14 +230,14 @@ static void load_material_texture( obj::Model &model,
|
||||
texture->setWrap(osg::Texture2D::WRAP_S, textureWrapMode);
|
||||
texture->setWrap(osg::Texture2D::WRAP_T, textureWrapMode);
|
||||
stateset->setTextureAttributeAndModes( texture_unit, texture,osg::StateAttribute::ON );
|
||||
|
||||
|
||||
if ( map.type == obj::Material::Map::REFLECTION )
|
||||
{
|
||||
osg::TexGen* texgen = new osg::TexGen;
|
||||
texgen->setMode(osg::TexGen::SPHERE_MAP);
|
||||
stateset->setTextureAttributeAndModes( texture_unit,texgen,osg::StateAttribute::ON );
|
||||
}
|
||||
|
||||
|
||||
if ( image->isImageTranslucent())
|
||||
{
|
||||
OSG_INFO<<"Found transparent image"<<std::endl;
|
||||
@@ -292,7 +292,7 @@ void ReaderWriterOBJ::buildMaterialToStateSetMap(obj::Model& model, MaterialToSt
|
||||
++numNotBlack;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (numNotBlack==0 && numBlack!=0)
|
||||
{
|
||||
for(itr = model.materialMap.begin();
|
||||
@@ -309,13 +309,13 @@ void ReaderWriterOBJ::buildMaterialToStateSetMap(obj::Model& model, MaterialToSt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for(obj::Model::MaterialMap::iterator itr = model.materialMap.begin();
|
||||
itr != model.materialMap.end();
|
||||
++itr)
|
||||
{
|
||||
obj::Material& material = itr->second;
|
||||
|
||||
|
||||
osg::ref_ptr< osg::StateSet > stateset = new osg::StateSet;
|
||||
|
||||
bool isTransparent = false;
|
||||
@@ -337,7 +337,7 @@ void ReaderWriterOBJ::buildMaterialToStateSetMap(obj::Model& model, MaterialToSt
|
||||
osg_material->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(0,0,0,1));
|
||||
}
|
||||
osg_material->setShininess(osg::Material::FRONT_AND_BACK,(material.Ns/1000.0f)*128.0f ); // note OBJ shiniess is 0..1000.
|
||||
|
||||
|
||||
if (material.ambient[3]!=1.0 ||
|
||||
material.diffuse[3]!=1.0 ||
|
||||
material.specular[3]!=1.0||
|
||||
@@ -347,8 +347,8 @@ void ReaderWriterOBJ::buildMaterialToStateSetMap(obj::Model& model, MaterialToSt
|
||||
isTransparent = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If the user has explicitly set the required texture type to unit map via the options
|
||||
|
||||
// If the user has explicitly set the required texture type to unit map via the options
|
||||
// string, then we load ONLY those textures that are in the map.
|
||||
if(localOptions.textureUnitAllocation.size()>0)
|
||||
{
|
||||
@@ -395,7 +395,7 @@ void ReaderWriterOBJ::buildMaterialToStateSetMap(obj::Model& model, MaterialToSt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (isTransparent)
|
||||
{
|
||||
stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
|
||||
@@ -408,17 +408,17 @@ void ReaderWriterOBJ::buildMaterialToStateSetMap(obj::Model& model, MaterialToSt
|
||||
|
||||
osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model, obj::Model::ElementList& elementList, ObjOptionsStruct& localOptions) const
|
||||
{
|
||||
|
||||
|
||||
unsigned int numVertexIndices = 0;
|
||||
unsigned int numNormalIndices = 0;
|
||||
unsigned int numTexCoordIndices = 0;
|
||||
|
||||
|
||||
unsigned int numPointElements = 0;
|
||||
unsigned int numPolylineElements = 0;
|
||||
unsigned int numPolygonElements = 0;
|
||||
|
||||
obj::Model::ElementList::iterator itr;
|
||||
|
||||
|
||||
if (localOptions.generateFacetNormals == true) {
|
||||
for(itr=elementList.begin();
|
||||
itr!=elementList.end();
|
||||
@@ -427,7 +427,7 @@ osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model,
|
||||
obj::Element& element = *(*itr);
|
||||
if (element.dataType==obj::Element::POINTS || element.dataType==obj::Element::POLYLINE)
|
||||
continue;
|
||||
|
||||
|
||||
if (element.normalIndices.size() == 0) {
|
||||
// fill in the normals
|
||||
int a = element.vertexIndices[0];
|
||||
@@ -450,9 +450,9 @@ osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for(itr=elementList.begin();
|
||||
itr!=elementList.end();
|
||||
++itr)
|
||||
@@ -470,27 +470,27 @@ osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model,
|
||||
}
|
||||
|
||||
if (numVertexIndices==0) return 0;
|
||||
|
||||
|
||||
if (numNormalIndices!=0 && numNormalIndices!=numVertexIndices)
|
||||
{
|
||||
OSG_NOTICE<<"Incorrect number of normals, ignore them"<<std::endl;
|
||||
numNormalIndices = 0;
|
||||
}
|
||||
|
||||
|
||||
if (numTexCoordIndices!=0 && numTexCoordIndices!=numVertexIndices)
|
||||
{
|
||||
OSG_NOTICE<<"Incorrect number of normals, ignore them"<<std::endl;
|
||||
numTexCoordIndices = 0;
|
||||
}
|
||||
|
||||
|
||||
osg::Vec3Array* vertices = numVertexIndices ? new osg::Vec3Array : 0;
|
||||
osg::Vec3Array* normals = numNormalIndices ? new osg::Vec3Array : 0;
|
||||
osg::Vec2Array* texcoords = numTexCoordIndices ? new osg::Vec2Array : 0;
|
||||
|
||||
|
||||
if (vertices) vertices->reserve(numVertexIndices);
|
||||
if (normals) normals->reserve(numNormalIndices);
|
||||
if (texcoords) texcoords->reserve(numTexCoordIndices);
|
||||
|
||||
|
||||
osg::Geometry* geometry = new osg::Geometry;
|
||||
if (vertices) geometry->setVertexArray(vertices);
|
||||
if (normals)
|
||||
@@ -502,7 +502,7 @@ osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model,
|
||||
{
|
||||
geometry->setTexCoordArray(0,texcoords);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (numPointElements>0)
|
||||
{
|
||||
@@ -546,7 +546,7 @@ osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model,
|
||||
osg::DrawArrays* drawArrays = new osg::DrawArrays(GL_POINTS,startPos,numPoints);
|
||||
geometry->addPrimitiveSet(drawArrays);
|
||||
}
|
||||
|
||||
|
||||
if (numPolylineElements>0)
|
||||
{
|
||||
unsigned int startPos = vertices->size();
|
||||
@@ -597,7 +597,7 @@ osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model,
|
||||
if (numPolygonElements>0)
|
||||
{
|
||||
unsigned int startPos = vertices->size();
|
||||
|
||||
|
||||
#ifdef USE_DRAWARRAYLENGTHS
|
||||
osg::DrawArrayLengths* drawArrayLengths = new osg::DrawArrayLengths(GL_POLYGON,startPos);
|
||||
geometry->addPrimitiveSet(drawArrayLengths);
|
||||
@@ -611,7 +611,7 @@ osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model,
|
||||
if (element.dataType==obj::Element::POLYGON)
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -633,7 +633,7 @@ osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model,
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
if (model.needReverse(element))
|
||||
{
|
||||
// need to reverse so add to OSG arrays in same order as in OBJ, as OSG assume anticlockwise ordering.
|
||||
@@ -697,7 +697,7 @@ osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model,
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
return geometry;
|
||||
}
|
||||
|
||||
@@ -717,7 +717,7 @@ osg::Node* ReaderWriterOBJ::convertModelToSceneGraph(obj::Model& model, ObjOptio
|
||||
itr!=model.elementStateMap.end();
|
||||
++itr)
|
||||
{
|
||||
|
||||
|
||||
const obj::ElementState& es = itr->first;
|
||||
obj::Model::ElementList& el = itr->second;
|
||||
|
||||
@@ -733,21 +733,21 @@ osg::Node* ReaderWriterOBJ::convertModelToSceneGraph(obj::Model& model, ObjOptio
|
||||
|
||||
osg::StateSet* stateset = materialToStateSetMap[es.materialName].get();
|
||||
geometry->setStateSet(stateset);
|
||||
|
||||
|
||||
// tesseleate any large polygons
|
||||
if (!localOptions.noTesselateLargePolygons)
|
||||
{
|
||||
osgUtil::Tessellator tessellator;
|
||||
tessellator.retessellatePolygons(*geometry);
|
||||
}
|
||||
|
||||
|
||||
// tri strip polygons to improve graphics peformance
|
||||
if (!localOptions.noTriStripPolygons)
|
||||
{
|
||||
osgUtil::TriStripVisitor tsv;
|
||||
tsv.stripify(*geometry);
|
||||
}
|
||||
|
||||
|
||||
// if no normals present add them.
|
||||
if (localOptions.generateFacetNormals==false && (!geometry->getNormalArray() || geometry->getNormalArray()->getNumElements()==0))
|
||||
{
|
||||
@@ -758,7 +758,7 @@ osg::Node* ReaderWriterOBJ::convertModelToSceneGraph(obj::Model& model, ObjOptio
|
||||
|
||||
osg::Geode* geode = new osg::Geode;
|
||||
geode->addDrawable(geometry);
|
||||
|
||||
|
||||
if (es.objectName.empty())
|
||||
{
|
||||
geode->setName(es.groupName);
|
||||
@@ -804,7 +804,7 @@ ReaderWriterOBJ::ObjOptionsStruct ReaderWriterOBJ::parseOptions(const osgDB::Rea
|
||||
{
|
||||
pre_equals = opt.substr(0,found);
|
||||
post_equals = opt.substr(found+1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pre_equals = opt;
|
||||
@@ -813,11 +813,11 @@ ReaderWriterOBJ::ObjOptionsStruct ReaderWriterOBJ::parseOptions(const osgDB::Rea
|
||||
if (pre_equals == "noRotation")
|
||||
{
|
||||
localOptions.rotate = false;
|
||||
}
|
||||
}
|
||||
else if (pre_equals == "noTesselateLargePolygons")
|
||||
{
|
||||
localOptions.noTesselateLargePolygons = true;
|
||||
}
|
||||
}
|
||||
else if (pre_equals == "noTriStripPolygons")
|
||||
{
|
||||
localOptions.noTriStripPolygons = true;
|
||||
@@ -827,8 +827,8 @@ ReaderWriterOBJ::ObjOptionsStruct ReaderWriterOBJ::parseOptions(const osgDB::Rea
|
||||
localOptions.generateFacetNormals = true;
|
||||
}
|
||||
else if (post_equals.length()>0)
|
||||
{
|
||||
obj::Material::Map::TextureMapType type = obj::Material::Map::UNKNOWN;
|
||||
{
|
||||
obj::Material::Map::TextureMapType type = obj::Material::Map::UNKNOWN;
|
||||
// Now we check to see if we have anything forcing a texture allocation
|
||||
if (pre_equals == "DIFFUSE") type = obj::Material::Map::DIFFUSE;
|
||||
else if (pre_equals == "AMBIENT") type = obj::Material::Map::AMBIENT;
|
||||
@@ -838,7 +838,7 @@ ReaderWriterOBJ::ObjOptionsStruct ReaderWriterOBJ::parseOptions(const osgDB::Rea
|
||||
else if (pre_equals == "BUMP") type = obj::Material::Map::BUMP;
|
||||
else if (pre_equals == "DISPLACEMENT") type = obj::Material::Map::DISPLACEMENT;
|
||||
else if (pre_equals == "REFLECTION") type = obj::Material::Map::REFLECTION;
|
||||
|
||||
|
||||
if (type!=obj::Material::Map::UNKNOWN)
|
||||
{
|
||||
int unit = atoi(post_equals.c_str()); // (probably should use istringstream rather than atoi)
|
||||
@@ -860,13 +860,13 @@ osgDB::ReaderWriter::ReadResult ReaderWriterOBJ::readNode(const std::string& fil
|
||||
|
||||
std::string fileName = osgDB::findDataFile( file, options );
|
||||
if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
|
||||
|
||||
|
||||
|
||||
|
||||
osgDB::ifstream fin(fileName.c_str());
|
||||
if (fin)
|
||||
{
|
||||
|
||||
// code for setting up the database path so that internally referenced file are searched for on relative paths.
|
||||
|
||||
// code for setting up the database path so that internally referenced file are searched for on relative paths.
|
||||
osg::ref_ptr<Options> local_opt = options ? static_cast<Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
|
||||
local_opt->setDatabasePath(osgDB::getFilePath(fileName));
|
||||
|
||||
@@ -879,7 +879,7 @@ osgDB::ReaderWriter::ReadResult ReaderWriterOBJ::readNode(const std::string& fil
|
||||
osg::Node* node = convertModelToSceneGraph(model, localOptions, options);
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
return ReadResult::FILE_NOT_HANDLED;
|
||||
}
|
||||
|
||||
@@ -891,12 +891,12 @@ osgDB::ReaderWriter::ReadResult ReaderWriterOBJ::readNode(std::istream& fin, con
|
||||
|
||||
obj::Model model;
|
||||
model.readOBJ(fin, options);
|
||||
|
||||
|
||||
ObjOptionsStruct localOptions = parseOptions(options);
|
||||
|
||||
|
||||
osg::Node* node = convertModelToSceneGraph(model, localOptions, options);
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
return ReadResult::FILE_NOT_HANDLED;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2004 Robert Osfield
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2004 Robert Osfield
|
||||
*
|
||||
* This library is open source and may be redistributed and/or modified under
|
||||
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||
* This library is open source and may be redistributed and/or modified under
|
||||
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
@@ -47,7 +47,7 @@ static Material::Map parseTextureMap( const std::string& ss, Material::Map::Text
|
||||
{
|
||||
if (s[0] != '-')
|
||||
break;
|
||||
|
||||
|
||||
int n;
|
||||
if (s[1] == 's' || s[1] == 'o')
|
||||
{
|
||||
@@ -136,7 +136,7 @@ bool Model::readline(std::istream& fin, char* line, const int LINE_SIZE)
|
||||
// OSG_NOTICE<<"We have dos line ending"<<std::endl;
|
||||
if (skipNewline)
|
||||
{
|
||||
skipNewline = false;
|
||||
skipNewline = false;
|
||||
*ptr++ = ' ';
|
||||
continue;
|
||||
}
|
||||
@@ -146,7 +146,7 @@ bool Model::readline(std::istream& fin, char* line, const int LINE_SIZE)
|
||||
// OSG_NOTICE<<"We have mac line ending"<<std::endl;
|
||||
if (skipNewline)
|
||||
{
|
||||
skipNewline = false;
|
||||
skipNewline = false;
|
||||
*ptr++ = ' ';
|
||||
continue;
|
||||
}
|
||||
@@ -166,7 +166,7 @@ bool Model::readline(std::istream& fin, char* line, const int LINE_SIZE)
|
||||
else if (c=='\\' && (p=='\r' || p=='\n'))
|
||||
{
|
||||
// need to keep return;
|
||||
skipNewline = true;
|
||||
skipNewline = true;
|
||||
}
|
||||
else if (c!=std::ifstream::traits_type::eof()) // don't copy eof.
|
||||
{
|
||||
@@ -178,10 +178,10 @@ bool Model::readline(std::istream& fin, char* line, const int LINE_SIZE)
|
||||
*ptr++ = c;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// strip trailing spaces
|
||||
while (ptr>line && *(ptr-1)==' ')
|
||||
{
|
||||
@@ -189,16 +189,16 @@ bool Model::readline(std::istream& fin, char* line, const int LINE_SIZE)
|
||||
}
|
||||
|
||||
*ptr = 0;
|
||||
|
||||
|
||||
if (changeTabsToSpaces)
|
||||
{
|
||||
|
||||
|
||||
for(ptr = line; *ptr != 0; ++ptr)
|
||||
{
|
||||
if (*ptr == '\t') *ptr=' ';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -447,7 +447,7 @@ bool Model::readMTL(std::istream& fin)
|
||||
}
|
||||
// map_opacity doesn't exist in the spec, but was already in the plugin
|
||||
// so leave it or plugin will break for some users
|
||||
else if (strncmp(line,"map_opacity ",12)==0)
|
||||
else if (strncmp(line,"map_opacity ",12)==0)
|
||||
{
|
||||
material->maps.push_back(parseTextureMap(strip(line+12),Material::Map::OPACITY));
|
||||
}
|
||||
@@ -495,7 +495,7 @@ bool Model::readMTL(std::istream& fin)
|
||||
{
|
||||
OSG_NOTICE <<"*** line not handled *** :"<<line<<std::endl;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -562,7 +562,7 @@ bool Model::readOBJ(std::istream& fin, const osgDB::ReaderWriter::Options* optio
|
||||
strncmp(line,"f ",2)==0)
|
||||
{
|
||||
char* ptr = line+2;
|
||||
|
||||
|
||||
Element* element = new Element( (line[0]=='p') ? Element::POINTS :
|
||||
(line[0]=='l') ? Element::POLYLINE :
|
||||
Element::POLYGON );
|
||||
@@ -574,7 +574,7 @@ bool Model::readOBJ(std::istream& fin, const osgDB::ReaderWriter::Options* optio
|
||||
{
|
||||
// skip white space
|
||||
while(*ptr==' ') ++ptr;
|
||||
|
||||
|
||||
if (sscanf(ptr, "%d/%d/%d", &vi, &ti, &ni) == 3)
|
||||
{
|
||||
// OSG_NOTICE<<" vi="<<vi<<"/ti="<<ti<<"/ni="<<ni<<std::endl;
|
||||
@@ -602,19 +602,19 @@ bool Model::readOBJ(std::istream& fin, const osgDB::ReaderWriter::Options* optio
|
||||
|
||||
// skip to white space or end of line
|
||||
while(*ptr!=' ' && *ptr!=0) ++ptr;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (!element->normalIndices.empty() && element->normalIndices.size() != element->vertexIndices.size())
|
||||
{
|
||||
element->normalIndices.clear();
|
||||
}
|
||||
|
||||
|
||||
if (!element->texCoordIndices.empty() && element->texCoordIndices.size() != element->vertexIndices.size())
|
||||
{
|
||||
element->texCoordIndices.clear();
|
||||
}
|
||||
|
||||
|
||||
if (!element->vertexIndices.empty())
|
||||
{
|
||||
Element::CoordinateCombination coordateCombination = element->getCoordinateCombination();
|
||||
@@ -704,7 +704,7 @@ bool Model::readOBJ(std::istream& fin, const osgDB::ReaderWriter::Options* optio
|
||||
int smoothingGroup=0;
|
||||
if (strncmp(line+2,"off",3)==0) smoothingGroup = 0;
|
||||
else sscanf(line+2,"%d",&smoothingGroup);
|
||||
|
||||
|
||||
if (currentElementState.smoothingGroup != smoothingGroup)
|
||||
{
|
||||
currentElementState.smoothingGroup = smoothingGroup;
|
||||
@@ -715,7 +715,7 @@ bool Model::readOBJ(std::istream& fin, const osgDB::ReaderWriter::Options* optio
|
||||
{
|
||||
OSG_NOTICE <<"*** line not handled *** :"<<line<<std::endl;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -725,7 +725,7 @@ bool Model::readOBJ(std::istream& fin, const osgDB::ReaderWriter::Options* optio
|
||||
OSG_NOTICE <<"texcoords :"<<texcoords.size()<<std::endl;
|
||||
OSG_NOTICE <<"materials :"<<materialMap.size()<<std::endl;
|
||||
OSG_NOTICE <<"elementStates :"<<elementStateMap.size()<<std::endl;
|
||||
|
||||
|
||||
unsigned int pos=0;
|
||||
for(ElementStateMap::iterator itr=elementStateMap.begin();
|
||||
itr!=elementStateMap.end();
|
||||
@@ -739,7 +739,7 @@ bool Model::readOBJ(std::istream& fin, const osgDB::ReaderWriter::Options* optio
|
||||
OSG_NOTICE<<" es.materialName="<<es.materialName<<std::endl;
|
||||
OSG_NOTICE<<" es.smoothGroup="<<es.smoothingGroup<<std::endl;
|
||||
OSG_NOTICE<<" ElementList ="<<el.size()<<std::endl;
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
@@ -753,7 +753,7 @@ void Model::addElement(Element* element)
|
||||
currentElementList = & (elementStateMap[currentElementState]);
|
||||
}
|
||||
currentElementList->push_back(element);
|
||||
|
||||
|
||||
}
|
||||
|
||||
osg::Vec3 Model::averageNormal(const Element& element) const
|
||||
@@ -766,7 +766,7 @@ osg::Vec3 Model::averageNormal(const Element& element) const
|
||||
normal += normals[*itr];
|
||||
}
|
||||
normal.normalize();
|
||||
|
||||
|
||||
return normal;
|
||||
}
|
||||
|
||||
@@ -782,13 +782,13 @@ osg::Vec3 Model::computeNormal(const Element& element) const
|
||||
normal += localNormal;
|
||||
}
|
||||
normal.normalize();
|
||||
|
||||
|
||||
return normal;
|
||||
}
|
||||
|
||||
bool Model::needReverse(const Element& element) const
|
||||
{
|
||||
if (element.normalIndices.empty()) return false;
|
||||
|
||||
|
||||
return computeNormal(element)*averageNormal(element) < 0.0f;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2004 Robert Osfield
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2004 Robert Osfield
|
||||
*
|
||||
* This library is open source and may be redistributed and/or modified under
|
||||
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||
* This library is open source and may be redistributed and/or modified under
|
||||
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
@@ -46,16 +46,16 @@ public:
|
||||
Ns(0),
|
||||
// textureReflection(false),
|
||||
alpha(1.0f) {}
|
||||
|
||||
|
||||
std::string name;
|
||||
|
||||
|
||||
osg::Vec4 ambient;
|
||||
osg::Vec4 diffuse;
|
||||
osg::Vec4 specular;
|
||||
osg::Vec4 emissive;
|
||||
float sharpness;
|
||||
int illum; // read but not implemented (would need specific shaders or state manipulation)
|
||||
|
||||
|
||||
osg::Vec4 Tf;
|
||||
int Ni;
|
||||
int Ns; // shininess 0..1000
|
||||
@@ -125,10 +125,10 @@ public:
|
||||
POLYLINE,
|
||||
POLYGON
|
||||
};
|
||||
|
||||
|
||||
Element(DataType type):
|
||||
dataType(type) {}
|
||||
|
||||
|
||||
enum CoordinateCombination
|
||||
{
|
||||
VERTICES,
|
||||
@@ -136,16 +136,16 @@ public:
|
||||
VERTICES_TEXCOORDS,
|
||||
VERTICES_NORMALS_TEXCOORDS
|
||||
};
|
||||
|
||||
|
||||
CoordinateCombination getCoordinateCombination() const
|
||||
{
|
||||
if (vertexIndices.size()==normalIndices.size())
|
||||
return (vertexIndices.size()==texCoordIndices.size()) ? VERTICES_NORMALS_TEXCOORDS : VERTICES_NORMALS;
|
||||
else
|
||||
else
|
||||
return (vertexIndices.size()==texCoordIndices.size()) ? VERTICES_TEXCOORDS : VERTICES;
|
||||
}
|
||||
|
||||
DataType dataType;
|
||||
|
||||
DataType dataType;
|
||||
IndexList vertexIndices;
|
||||
IndexList normalIndices;
|
||||
IndexList texCoordIndices;
|
||||
@@ -158,7 +158,7 @@ public:
|
||||
ElementState():
|
||||
coordinateCombination(Element::VERTICES),
|
||||
smoothingGroup(0) {}
|
||||
|
||||
|
||||
bool operator < (const ElementState& rhs) const
|
||||
{
|
||||
if (materialName<rhs.materialName) return true;
|
||||
@@ -189,41 +189,41 @@ class Model
|
||||
public:
|
||||
Model():
|
||||
currentElementList(0) {}
|
||||
|
||||
|
||||
void setDatabasePath(const std::string& path) { databasePath = path; }
|
||||
const std::string& getDatabasePath() const { return databasePath; }
|
||||
|
||||
std::string lastComponent(const char* linep);
|
||||
bool readMTL(std::istream& fin);
|
||||
bool readOBJ(std::istream& fin, const osgDB::ReaderWriter::Options* options);
|
||||
|
||||
|
||||
bool readline(std::istream& fin, char* line, const int LINE_SIZE);
|
||||
void addElement(Element* element);
|
||||
|
||||
|
||||
osg::Vec3 averageNormal(const Element& element) const;
|
||||
osg::Vec3 computeNormal(const Element& element) const;
|
||||
bool needReverse(const Element& element) const;
|
||||
|
||||
|
||||
int remapVertexIndex(int vi) { return (vi<0) ? vertices.size()+vi : vi-1; }
|
||||
int remapNormalIndex(int vi) { return (vi<0) ? normals.size()+vi : vi-1; }
|
||||
int remapTexCoordIndex(int vi) { return (vi<0) ? texcoords.size()+vi : vi-1; }
|
||||
|
||||
|
||||
typedef std::map<std::string,Material> MaterialMap;
|
||||
typedef std::vector< osg::Vec2 > Vec2Array;
|
||||
typedef std::vector< osg::Vec3 > Vec3Array;
|
||||
typedef std::vector< osg::ref_ptr<Element> > ElementList;
|
||||
typedef std::map< ElementState,ElementList > ElementStateMap;
|
||||
|
||||
|
||||
|
||||
std::string databasePath;
|
||||
MaterialMap materialMap;
|
||||
|
||||
|
||||
Vec3Array vertices;
|
||||
Vec3Array normals;
|
||||
Vec2Array texcoords;
|
||||
|
||||
|
||||
ElementState currentElementState;
|
||||
|
||||
|
||||
ElementStateMap elementStateMap;
|
||||
ElementList* currentElementList;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user