openscenegraph
TriangleFunctor
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 OSG_TRIANGLEFUNCTOR
15#define OSG_TRIANGLEFUNCTOR 1
16
17#include <osg/PrimitiveSet>
18#include <osg/Notify>
19
20namespace osg {
21
22
23/** Provides access to the triangles that compose an \c osg::Drawable. If the \c
24 * Drawable is not composed of triangles, the \c TriangleFunctor will convert
25 * the primitives to triangles whenever possible.
26 * <p>Notice that \c TriangleFunctor is a class template, and that it inherits
27 * from its template parameter \c T. This template parameter must implement
28 * <tt>T::operator() (const osg::Vec3 v1, const osg::Vec3 v2, const osg::Vec3
29 * v3, bool treatVertexDataAsTemporary)</tt>, which will be called for every
30 * triangle when the functor is applied to a \c Drawable. Parameters \c v1, \c
31 * v2, and \c v3 are the triangle vertices. The fourth parameter, \c
32 * treatVertexDataAsTemporary, indicates whether these vertices are coming from
33 * a "real" vertex array, or from a temporary vertex array, created by the \c
34 * TriangleFunctor from some other geometry representation.
35 * @see \c PrimitiveFunctor for general usage hints.
36 */
37template<class T>
38class TriangleFunctor : public PrimitiveFunctor, public T
39{
40public:
41
42 TriangleFunctor()
43 {
44 _vertexArraySize=0;
45 _vertexArrayPtr=0;
46 }
47
48 virtual ~TriangleFunctor() {}
49
50 virtual void setVertexArray(unsigned int,const Vec2*)
51 {
52 notify(WARN)<<"Triangle Functor does not support Vec2* vertex arrays"<<std::endl;
53 }
54
55 virtual void setVertexArray(unsigned int count,const Vec3* vertices)
56 {
57 _vertexArraySize = count;
58 _vertexArrayPtr = vertices;
59 }
60
61 virtual void setVertexArray(unsigned int,const Vec4* )
62 {
63 notify(WARN)<<"Triangle Functor does not support Vec4* vertex arrays"<<std::endl;
64 }
65
66 virtual void setVertexArray(unsigned int,const Vec2d*)
67 {
68 notify(WARN)<<"Triangle Functor does not support Vec2d* vertex arrays"<<std::endl;
69 }
70
71 virtual void setVertexArray(unsigned int,const Vec3d*)
72 {
73 notify(WARN)<<"Triangle Functor does not support Vec3d* vertex arrays"<<std::endl;
74 }
75
76 virtual void setVertexArray(unsigned int,const Vec4d* )
77 {
78 notify(WARN)<<"Triangle Functor does not support Vec4d* vertex arrays"<<std::endl;
79 }
80
81 virtual void drawArrays(GLenum mode,GLint first,GLsizei count)
82 {
83 if (_vertexArrayPtr==0 || count==0) return;
84
85 switch(mode)
86 {
87 case(GL_TRIANGLES):
88 {
89 const Vec3* vlast = &_vertexArrayPtr[first+count];
90 for(const Vec3* vptr=&_vertexArrayPtr[first];vptr<vlast;vptr+=3)
91 this->operator()(*(vptr),*(vptr+1),*(vptr+2));
92 break;
93 }
94 case(GL_TRIANGLE_STRIP):
95 {
96 const Vec3* vptr = &_vertexArrayPtr[first];
97 for(GLsizei i=2;i<count;++i,++vptr)
98 {
99 if ((i%2)) this->operator()(*(vptr),*(vptr+2),*(vptr+1));
100 else this->operator()(*(vptr),*(vptr+1),*(vptr+2));
101 }
102 break;
103 }
104 case(GL_QUADS):
105 {
106 const Vec3* vptr = &_vertexArrayPtr[first];
107 for(GLsizei i=3;i<count;i+=4,vptr+=4)
108 {
109 this->operator()(*(vptr),*(vptr+1),*(vptr+2));
110 this->operator()(*(vptr),*(vptr+2),*(vptr+3));
111 }
112 break;
113 }
114 case(GL_QUAD_STRIP):
115 {
116 const Vec3* vptr = &_vertexArrayPtr[first];
117 for(GLsizei i=3;i<count;i+=2,vptr+=2)
118 {
119 this->operator()(*(vptr),*(vptr+1),*(vptr+2));
120 this->operator()(*(vptr+1),*(vptr+3),*(vptr+2));
121 }
122 break;
123 }
124 case(GL_POLYGON): // treat polygons as GL_TRIANGLE_FAN
125 case(GL_TRIANGLE_FAN):
126 {
127 const Vec3* vfirst = &_vertexArrayPtr[first];
128 const Vec3* vptr = vfirst+1;
129 for(GLsizei i=2;i<count;++i,++vptr)
130 {
131 this->operator()(*(vfirst),*(vptr),*(vptr+1));
132 }
133 break;
134 }
135 case(GL_POINTS):
136 case(GL_LINES):
137 case(GL_LINE_STRIP):
138 case(GL_LINE_LOOP):
139 default:
140 // can't be converted into to triangles.
141 break;
142 }
143 }
144
145 virtual void drawElements(GLenum mode,GLsizei count,const GLubyte* indices)
146 {
147 if (indices==0 || count==0) return;
148
149 typedef const GLubyte* IndexPointer;
150
151 switch(mode)
152 {
153 case(GL_TRIANGLES):
154 {
155 IndexPointer ilast = &indices[count];
156 for(IndexPointer iptr=indices;iptr<ilast;iptr+=3)
157 this->operator()(_vertexArrayPtr[*iptr],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)]);
158 break;
159 }
160 case(GL_TRIANGLE_STRIP):
161 {
162 IndexPointer iptr = indices;
163 for(GLsizei i=2;i<count;++i,++iptr)
164 {
165 if ((i%2)) this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+2)],_vertexArrayPtr[*(iptr+1)]);
166 else this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)]);
167 }
168 break;
169 }
170 case(GL_QUADS):
171 {
172 IndexPointer iptr = indices;
173 for(GLsizei i=3;i<count;i+=4,iptr+=4)
174 {
175 this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)]);
176 this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+2)],_vertexArrayPtr[*(iptr+3)]);
177 }
178 break;
179 }
180 case(GL_QUAD_STRIP):
181 {
182 IndexPointer iptr = indices;
183 for(GLsizei i=3;i<count;i+=2,iptr+=2)
184 {
185 this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)]);
186 this->operator()(_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+3)],_vertexArrayPtr[*(iptr+2)]);
187 }
188 break;
189 }
190 case(GL_POLYGON): // treat polygons as GL_TRIANGLE_FAN
191 case(GL_TRIANGLE_FAN):
192 {
193 IndexPointer iptr = indices;
194 const Vec3& vfirst = _vertexArrayPtr[*iptr];
195 ++iptr;
196 for(GLsizei i=2;i<count;++i,++iptr)
197 {
198 this->operator()(vfirst,_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)]);
199 }
200 break;
201 }
202 case(GL_POINTS):
203 case(GL_LINES):
204 case(GL_LINE_STRIP):
205 case(GL_LINE_LOOP):
206 default:
207 // can't be converted into to triangles.
208 break;
209 }
210 }
211
212 virtual void drawElements(GLenum mode,GLsizei count,const GLushort* indices)
213 {
214 if (indices==0 || count==0) return;
215
216 typedef const GLushort* IndexPointer;
217
218 switch(mode)
219 {
220 case(GL_TRIANGLES):
221 {
222 IndexPointer ilast = &indices[count];
223 for(IndexPointer iptr=indices;iptr<ilast;iptr+=3)
224 {
225 this->operator()(_vertexArrayPtr[*iptr],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)]);
226 }
227 break;
228 }
229 case(GL_TRIANGLE_STRIP):
230 {
231 IndexPointer iptr = indices;
232 for(GLsizei i=2;i<count;++i,++iptr)
233 {
234 if ((i%2)) this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+2)],_vertexArrayPtr[*(iptr+1)]);
235 else this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)]);
236 }
237 break;
238 }
239 case(GL_QUADS):
240 {
241 IndexPointer iptr = indices;
242 for(GLsizei i=3;i<count;i+=4,iptr+=4)
243 {
244 this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)]);
245 this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+2)],_vertexArrayPtr[*(iptr+3)]);
246 }
247 break;
248 }
249 case(GL_QUAD_STRIP):
250 {
251 IndexPointer iptr = indices;
252 for(GLsizei i=3;i<count;i+=2,iptr+=2)
253 {
254 this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)]);
255 this->operator()(_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+3)],_vertexArrayPtr[*(iptr+2)]);
256 }
257 break;
258 }
259 case(GL_POLYGON): // treat polygons as GL_TRIANGLE_FAN
260 case(GL_TRIANGLE_FAN):
261 {
262 IndexPointer iptr = indices;
263 const Vec3& vfirst = _vertexArrayPtr[*iptr];
264 ++iptr;
265 for(GLsizei i=2;i<count;++i,++iptr)
266 {
267 this->operator()(vfirst,_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)]);
268 }
269 break;
270 }
271 case(GL_POINTS):
272 case(GL_LINES):
273 case(GL_LINE_STRIP):
274 case(GL_LINE_LOOP):
275 default:
276 // can't be converted into to triangles.
277 break;
278 }
279 }
280
281 virtual void drawElements(GLenum mode,GLsizei count,const GLuint* indices)
282 {
283 if (indices==0 || count==0) return;
284
285 typedef const GLuint* IndexPointer;
286
287 switch(mode)
288 {
289 case(GL_TRIANGLES):
290 {
291 IndexPointer ilast = &indices[count];
292 for(IndexPointer iptr=indices;iptr<ilast;iptr+=3)
293 this->operator()(_vertexArrayPtr[*iptr],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)]);
294 break;
295 }
296 case(GL_TRIANGLE_STRIP):
297 {
298 IndexPointer iptr = indices;
299 for(GLsizei i=2;i<count;++i,++iptr)
300 {
301 if ((i%2)) this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+2)],_vertexArrayPtr[*(iptr+1)]);
302 else this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)]);
303 }
304 break;
305 }
306 case(GL_QUADS):
307 {
308 IndexPointer iptr = indices;
309 for(GLsizei i=3;i<count;i+=4,iptr+=4)
310 {
311 this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)]);
312 this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+2)],_vertexArrayPtr[*(iptr+3)]);
313 }
314 break;
315 }
316 case(GL_QUAD_STRIP):
317 {
318 IndexPointer iptr = indices;
319 for(GLsizei i=3;i<count;i+=2,iptr+=2)
320 {
321 this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)]);
322 this->operator()(_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+3)],_vertexArrayPtr[*(iptr+2)]);
323 }
324 break;
325 }
326 case(GL_POLYGON): // treat polygons as GL_TRIANGLE_FAN
327 case(GL_TRIANGLE_FAN):
328 {
329 IndexPointer iptr = indices;
330 const Vec3& vfirst = _vertexArrayPtr[*iptr];
331 ++iptr;
332 for(GLsizei i=2;i<count;++i,++iptr)
333 {
334 this->operator()(vfirst,_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)]);
335 }
336 break;
337 }
338 case(GL_POINTS):
339 case(GL_LINES):
340 case(GL_LINE_STRIP):
341 case(GL_LINE_LOOP):
342 default:
343 // can't be converted into to triangles.
344 break;
345 }
346 }
347
348protected:
349
350
351 unsigned int _vertexArraySize;
352 const Vec3* _vertexArrayPtr;
353};
354
355}
356
357#endif