1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield 2 * 3 * This library is open source and may be redistributed and/or modified under 4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or 5 * (at your option) any later version. The full license is in LICENSE file 6 * included with this distribution, and on the openscenegraph.org website. 7 * 8 * This library is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * OpenSceneGraph Public License for more details. 12*/ 13 14#ifndef OSGUTIL_Tessellator 15#define OSGUTIL_Tessellator 16 17#include <osg/Geometry> 18 19#include <osgUtil/Export> 20 21#include <osg/GLU> 22 23#include <vector> 24 25#ifndef CALLBACK 26 /* Win32 calling conventions. (or a least that's what the GLUT example tess.c uses.)*/ 27 #define CALLBACK 28#endif 29 30namespace osgUtil { 31 32/** Originally a simple class for tessellating a single polygon boundary. 33 * Using old style glu tessellation functions for portability. 34 * Upgraded Jan 2004 to use the modern glu tessellation functions.*/ 35 36class OSGUTIL_EXPORT Tessellator : public osg::Referenced 37{ 38 public: 39 40 Tessellator(); 41 ~Tessellator(); 42 43 /** The winding rule, see red book ch 11. */ 44 enum WindingType{ 45 TESS_WINDING_ODD = GLU_TESS_WINDING_ODD, 46 TESS_WINDING_NONZERO = GLU_TESS_WINDING_NONZERO, 47 TESS_WINDING_POSITIVE = GLU_TESS_WINDING_POSITIVE, 48 TESS_WINDING_NEGATIVE = GLU_TESS_WINDING_NEGATIVE, 49 TESS_WINDING_ABS_GEQ_TWO = GLU_TESS_WINDING_ABS_GEQ_TWO 50 } ; 51 52 /** we interpret all contours in the geometry as a single set to be tessellated or 53 * each separate drawable's contours needs to be tessellated. */ 54 enum TessellationType { 55 TESS_TYPE_GEOMETRY, // tessellate everything in the geometry object 56 TESS_TYPE_DRAWABLE, // tessellate each polygon, triangles & quads drawables in geometry separately 57 TESS_TYPE_POLYGONS // tessellate ONLY polygon drawables in geometry separately 58 }; 59 60 /** Set and get tessellation request boundary only on/off */ 61 void setBoundaryOnly (const bool tt) { _boundaryOnly=tt;} 62 inline bool getBoundaryOnly ( ) { return _boundaryOnly;} 63 64 /** Set and get tessellation windong rule */ 65 void setWindingType (const WindingType wt) { _wtype=wt;} 66 inline WindingType getWindingType ( ) { return _wtype;} 67 68 /** Set and get tessellation type */ 69 void setTessellationType (const TessellationType tt) { _ttype=tt;} 70 inline TessellationType getTessellationType ( ) { return _ttype;} 71 72 /** Change the contours lists of the geometry into tessellated primitives (the 73 * list of primitives in the original geometry is stored in the Tessellator for 74 * possible re-use. 75 * The name remains retessellatePolygons although it now handles trifans, strips, quads etc. 76 * as well as Polygons so as to not break old codes relying on this function name. */ 77 void retessellatePolygons(osg::Geometry &cxgeom); 78 79 /** Define the normal to the tessellated polygon - this provides a hint how to 80 * tessellate the contours; see gluTessNormal in red book or man pages. 81 * GWM July 2005. Can improve teselation 82 * "For example, if you know that all polygons lie in the x-y plane, 83 * call gluTessNormal(tess, 0.0, 0.0, 1.0) before rendering any polygons." 84 */ 85 void setTessellationNormal(const osg::Vec3 norm) { tessNormal=norm;} 86 87 osg::Geometry::PrimitiveSetList getContours() { return _Contours;} 88 89 struct Prim : public osg::Referenced 90 { 91 Prim(GLenum mode):_mode(mode) {} 92 93 typedef std::vector<osg::Vec3*> VecList; 94 95 GLenum _mode; 96 VecList _vertices; 97 }; 98 99 virtual void beginTessellation(); 100 101 void beginContour(); 102 103 /** Add a vertex to the current contour, see gluTessVertex for details. 104 * Note the vertex pointer is returned at the end of tessellation and 105 * must not be left dangling or be overwritten until all results are 106 * collected. 107 */ 108 void addVertex(osg::Vec3* vertex); 109 110 void endContour(); 111 112 void endTessellation(); 113 114 typedef std::vector< osg::ref_ptr<Prim> > PrimList; 115 116 PrimList& getPrimList() { return _primList; } 117 118 void reset(); 119 120 protected: 121 122 /** remove unused parts of the array, eg for when retessellating 123 * tessellation can introduce extra vertices for concave or crossing boundaries, 124 * these will leak memory if not removed when retessellating. */ 125 void reduceArray(osg::Array * cold, const unsigned int nnu); 126 127 void collectTessellation(osg::Geometry &cxgeom, unsigned int originalIndex); 128 129 typedef std::map<osg::Vec3*,unsigned int> VertexPtrToIndexMap; 130 void addContour(GLenum mode, unsigned int first, unsigned int last, osg::Vec3Array* vertices); 131 void addContour(osg::PrimitiveSet* primitive, osg::Vec3Array* vertices); 132 void handleNewVertices(osg::Geometry& geom,VertexPtrToIndexMap &vertexPtrToIndexMap); 133 134 void begin(GLenum mode); 135 void vertex(osg::Vec3* vertex); 136 void combine(osg::Vec3* vertex,void* vertex_data[4],GLfloat weight[4]); 137 void end(); 138 void error(GLenum errorCode); 139 140 141 static void CALLBACK beginCallback(GLenum which, void* userData); 142 static void CALLBACK vertexCallback(GLvoid *data, void* userData); 143 static void CALLBACK combineCallback(GLdouble coords[3], void* vertex_data[4], 144 GLfloat weight[4], void** outData, 145 void* useData); 146 static void CALLBACK endCallback(void* userData); 147 static void CALLBACK errorCallback(GLenum errorCode, void* userData); 148 149 150 struct Vec3d 151 { 152 double _v[3]; 153 }; 154 155 156 struct NewVertex 157 { 158 159 NewVertex(): 160 _vpos(0), 161 _f1(0), 162 _v1(0), 163 _f2(0), 164 _v2(0), 165 _f3(0), 166 _v3(0), 167 _f4(0), 168 _v4(0) {} 169 170 NewVertex(const NewVertex& nv): 171 _vpos(nv._vpos), 172 _f1(nv._f1), 173 _v1(nv._v1), 174 _f2(nv._f2), 175 _v2(nv._v2), 176 _f3(nv._f3), 177 _v3(nv._v3), 178 _f4(nv._f4), 179 _v4(nv._v4) {} 180 181 NewVertex(osg::Vec3* vx, 182 float f1,osg::Vec3* v1, 183 float f2,osg::Vec3* v2, 184 float f3,osg::Vec3* v3, 185 float f4,osg::Vec3* v4): 186 _vpos(vx), 187 _f1(f1), 188 _v1(v1), 189 _f2(f2), 190 _v2(v2), 191 _f3(f3), 192 _v3(v3), 193 _f4(f4), 194 _v4(v4) {} 195 196 osg::Vec3 *_vpos; // added gwm Jan 2004 the vertex coords s.t. NewVertex can be used in a std::vector 197 198 float _f1; 199 osg::Vec3* _v1; 200 201 float _f2; 202 osg::Vec3* _v2; 203 204 float _f3; 205 osg::Vec3* _v3; 206 207 float _f4; 208 osg::Vec3* _v4; 209 210 }; 211 212 //change NewVertexList from std::map<osg::Vec3*,NewVertex> NewVertexList; 213 // because this has undefined order of insertion for new vertices. 214 // which occasionally corrupted the texture mapping. 215 typedef std::vector<NewVertex> NewVertexList; 216 typedef std::vector<Vec3d*> Vec3dList; 217 218 osg::GLUtesselator* _tobj; 219 220 PrimList _primList; 221 Vec3dList _coordData; 222 NewVertexList _newVertexList; 223 GLenum _errorCode; 224 225 /** winding rule, which parts will become solid */ 226 WindingType _wtype; 227 228 /** tessellation rule, which parts will become solid */ 229 TessellationType _ttype; 230 231 bool _boundaryOnly; // see gluTessProperty - if true: make the boundary edges only. 232 233 /** number of vertices that are part of the 'original' set of contours */ 234 unsigned int _numberVerts; 235 236 /** List of primitives that define the contours */ 237 osg::Geometry::PrimitiveSetList _Contours; 238 239 /** count number of primitives in a geometry to get right no. of norms/colurs etc for per_primitive attributes. */ 240 unsigned int _index; 241 242 /** the gluTessNormal for tessellation hint */ 243 osg::Vec3 tessNormal; 244 245 /** count of number of extra primitives added */ 246 unsigned int _extraPrimitives; 247}; 248 249} 250 251#endif 252