Tessellator 8.7 KB

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