openscenegraph
Tessellator
Go to the documentation of this file.
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