objwriternodevisitor.cpp
来自「最新osg包」· C++ 代码 · 共 575 行 · 第 1/2 页
CPP
575 行
// -*-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/ */#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), _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::Vec3 & inv) { osg::Vec3 v(inv); if (_applyMatrix) v = (_isNormal) ? (v * _m) - _origin : v * _m; _fout << v[0] << ' ' << v[1] << ' ' << v[2]; } virtual void apply (osg::Vec2b & inv) { _fout << inv[0] << ' ' << inv[1]; } 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]; } virtual void apply (osg::Vec2s & inv) { _fout << inv[0] << ' ' << inv[1]; } 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]; } private: std::ostream& _fout; osg::Matrix _m; bool _applyMatrix, _isNormal; osg::Vec3 _origin;};/** writes all primitives of a primitive-set out to a stream, decomposes quads to triangles, line-strips to lines etc */class PrimitiveIndexWriter : public osg::PrimitiveIndexFunctor { public: PrimitiveIndexWriter(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), _lastTexIndex(lastTexIndex), _hasNormalCoords(geo->getNormalArray() != NULL), _hasTexCoords(geo->getTexCoordArray(0) != NULL), _geo(geo), _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) { _fout << (i + _lastVertexIndex) << "/"; if (_hasTexCoords || _hasNormalCoords) { if (_hasTexCoords) _fout << (i + _lastTexIndex); _fout << "/"; if (_hasNormalCoords) { if (_geo->getNormalBinding() == osg::Geometry::BIND_PER_VERTEX) _fout << (i+_lastNormalIndex); else _fout << (_normalIndex + _lastNormalIndex); } } _fout << " "; } // operator for triangles void writeTriangle(unsigned int i1, unsigned int i2, unsigned int i3) { _fout << "f "; write(i1); write(i2); write(i3); _fout << std::endl; // 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) { _fout << "l "; write(i1); write(i2); _fout << std::endl; // 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) { _fout << "p "; write(i1); _fout << std::endl; // not sure if this is correct? if(_geo->getNormalBinding() && _geo->getNormalBinding() == osg::Geometry::BIND_PER_PRIMITIVE) ++_normalIndex; } virtual void begin(GLenum mode) { _modeCache = mode; _indexCache.clear(); } virtual void vertex(unsigned int vert) { _indexCache.push_back(vert); } virtual void end() { if (!_indexCache.empty()) { drawElements(_modeCache,_indexCache.size(),&_indexCache.front()); } } virtual void drawArrays(GLenum mode,GLint first,GLsizei count); virtual void drawElements(GLenum mode,GLsizei count,const GLubyte* indices) { drawElementsImplementation<GLubyte>(mode, count, indices); } 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) { if (indices==0 || count==0) return; typedef const T* IndexPointer; switch(mode) { case(GL_TRIANGLES): { IndexPointer ilast = &indices[count]; for(IndexPointer iptr=indices;iptr<ilast;iptr+=3) writeTriangle(*iptr,*(iptr+1),*(iptr+2)); break; } case(GL_TRIANGLE_STRIP): { IndexPointer iptr = indices; for(GLsizei i=2;i<count;++i,++iptr) { if ((i%2)) writeTriangle(*(iptr),*(iptr+2),*(iptr+1)); else writeTriangle(*(iptr),*(iptr+1),*(iptr+2)); } break; } case(GL_QUADS): { IndexPointer iptr = indices; for(GLsizei i=3;i<count;i+=4,iptr+=4) { writeTriangle(*(iptr),*(iptr+1),*(iptr+2)); writeTriangle(*(iptr),*(iptr+2),*(iptr+3)); } break; } case(GL_QUAD_STRIP): { IndexPointer iptr = indices; for(GLsizei i=3;i<count;i+=2,iptr+=2) { writeTriangle(*(iptr),*(iptr+1),*(iptr+2)); writeTriangle(*(iptr+1),*(iptr+3),*(iptr+2)); } break; } case(GL_POLYGON): // treat polygons as GL_TRIANGLE_FAN case(GL_TRIANGLE_FAN): { IndexPointer iptr = indices; unsigned int first = *iptr; ++iptr; for(GLsizei i=2;i<count;++i,++iptr) { writeTriangle(first,*(iptr),*(iptr+1)); } break; } case(GL_POINTS): { IndexPointer ilast = &indices[count]; for(IndexPointer iptr=indices;iptr<ilast;++iptr) { writePoint(*iptr); } break; } case(GL_LINES): { IndexPointer ilast = &indices[count]; for(IndexPointer iptr=indices;iptr<ilast;iptr+=2) { writeLine(*iptr, *(iptr+1)); } break; } case(GL_LINE_STRIP): { IndexPointer ilast = &indices[count]; for(IndexPointer iptr=indices+1;iptr<ilast;iptr+=2) { writeLine(*(iptr-1), *iptr); } break; } case(GL_LINE_LOOP): {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?