/* -*-c++-*- OpenSceneGraph - Copyright (C) Sketchfab * * This application is open source and may be redistributed and/or modified * freely and without restriction, both in commercial and non commercial * applications, as long as this copyright notice is maintained. * * This application 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. * */ #ifndef TRIANGLE_LINE_POINT_INDEX_FUNCTOR #define TRIANGLE_LINE_POINT_INDEX_FUNCTOR #include #include template class TriangleLinePointIndexFunctor : public osg::PrimitiveIndexFunctor, public T { public: 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* ) {} 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) { switch(mode) { case(GL_TRIANGLES): { unsigned int pos=first; for(GLsizei i = 2 ; i < count ; i += 3, pos += 3) { this->operator()(pos, pos + 1, pos + 2); } break; } case(GL_TRIANGLE_STRIP): { unsigned int pos = first; for(GLsizei i = 2 ; i < count ; ++ i, ++ pos) { if ((i%2)) this->operator()(pos, pos + 2, pos + 1); else this->operator()(pos, pos + 1, pos + 2); } break; } case(GL_QUADS): { unsigned int pos = first; for(GLsizei i = 3 ; i < count ; i += 4, pos += 4) { this->operator()(pos,pos + 1, pos + 2); this->operator()(pos,pos + 2, pos + 3); } break; } case(GL_QUAD_STRIP): { unsigned int pos = first; for(GLsizei i = 3 ; i < count ; i += 2, pos += 2) { this->operator()(pos, pos + 1,pos + 2); this->operator()(pos + 1,pos + 3,pos + 2); } break; } case(GL_POLYGON): // treat polygons as GL_TRIANGLE_FAN case(GL_TRIANGLE_FAN): { unsigned int pos = first + 1; for(GLsizei i = 2 ; i < count ; ++ i, ++ pos) { this->operator()(first, pos, pos + 1); } break; } case(GL_LINES): { unsigned int pos = first; for(GLsizei i = 0 ; i < count ; i += 2, pos += 2) { this->operator()(pos, pos + 1); } break; } case(GL_LINE_STRIP): { unsigned int pos = first; for(GLsizei i = 0 ; i < count - 1 ; i += 1, pos += 1) { this->operator()(pos, pos + 1); } break; } case(GL_LINE_LOOP): { unsigned int pos = first; for(GLsizei i = 0 ; i < count - 1 ; i += 1, pos += 1) { this->operator()(pos, pos + 1); } this->operator()(pos, first); break; } case(GL_POINTS): { unsigned int pos=first; for(GLsizei i = 0 ; i < count ; ++ i) { this->operator()(pos + i); } break; } default: break; } } template void drawElements(GLenum mode, GLsizei count, const I* indices) { typedef I Index; typedef const I* IndexPointer; if (indices == 0 || count == 0) { return; } switch(mode) { case(GL_TRIANGLES): { IndexPointer ilast = &indices[count]; for(IndexPointer iptr = indices ; iptr < ilast ; iptr += 3) { this->operator()(*iptr, *(iptr + 1), *(iptr + 2)); } break; } case(GL_TRIANGLE_STRIP): { IndexPointer iptr = indices; for(GLsizei i = 2 ; i < count ; ++ i, ++ iptr) { if ((i%2)) this->operator()(*(iptr), *(iptr + 2), *(iptr + 1)); else this->operator()(*(iptr), *(iptr + 1), *(iptr + 2)); } break; } case(GL_QUADS): { IndexPointer iptr = indices; for(GLsizei i = 3 ; i < count ; i += 4, iptr += 4) { this->operator()(*(iptr), *(iptr + 1), *(iptr + 2)); this->operator()(*(iptr), *(iptr + 2), *(iptr + 3)); } break; } case(GL_QUAD_STRIP): { IndexPointer iptr = indices; for(GLsizei i = 3 ; i < count ; i += 2, iptr += 2) { this->operator()(*(iptr), *(iptr + 1), *(iptr + 2)); this->operator()(*(iptr + 1), *(iptr + 3), *(iptr + 2)); } break; } case(GL_POLYGON): // treat polygons as GL_TRIANGLE_FAN case(GL_TRIANGLE_FAN): { IndexPointer iptr = indices; Index first = *iptr; ++iptr; for(GLsizei i = 2 ; i < count ; ++ i, ++ iptr) { this->operator()(first, *(iptr), *(iptr + 1)); } break; } case(GL_LINES): { const I* iptr = indices; for(GLsizei i = 0 ; i < count ; i += 2, iptr += 2) { this->operator()(*iptr, *(iptr + 1)); } break; } case(GL_LINE_STRIP): { const I* iptr = indices; for(GLsizei i = 0 ; i < count - 1 ; i += 1, iptr += 1) { this->operator()(*iptr, *(iptr + 1)); } break; } case(GL_LINE_LOOP): { const I* iptr = indices; I first = *iptr; for(GLsizei i = 0 ; i < count - 1 ; i += 1, iptr += 1) { this->operator()(*iptr, *(iptr + 1)); } this->operator()(*iptr, first); break; } case GL_POINTS: { IndexPointer ilast = &indices[count]; for(IndexPointer iptr = indices ; iptr < ilast ; iptr += 1) { this->operator()(*iptr); } break; } default: break; } } virtual void drawElements(GLenum mode, GLsizei count, const GLubyte* indices) { drawElements(mode, count, indices); } virtual void drawElements(GLenum mode,GLsizei count,const GLushort* indices) { drawElements(mode, count, indices); } virtual void drawElements(GLenum mode,GLsizei count,const GLuint* indices) { drawElements(mode, count, indices); } GLenum _modeCache; std::vector _indexCache; std::vector _remap; }; #endif