root/OpenSceneGraph/trunk/include/osg/TriangleFunctor @ 13041

Revision 13041, 15.4 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
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        _modeCache=0;
47        _treatVertexDataAsTemporary=false;
48    }
49
50    virtual ~TriangleFunctor() {}
51
52    void setTreatVertexDataAsTemporary(bool treatVertexDataAsTemporary) { _treatVertexDataAsTemporary=treatVertexDataAsTemporary; }
53    bool getTreatVertexDataAsTemporary() const { return _treatVertexDataAsTemporary; }
54
55    virtual void setVertexArray(unsigned int,const Vec2*)
56    {
57        notify(WARN)<<"Triangle Functor does not support Vec2* vertex arrays"<<std::endl;
58    }
59
60    virtual void setVertexArray(unsigned int count,const Vec3* vertices)
61    {
62        _vertexArraySize = count;
63        _vertexArrayPtr = vertices;
64    }
65
66    virtual void setVertexArray(unsigned int,const Vec4* )
67    {
68        notify(WARN)<<"Triangle Functor does not support Vec4* vertex arrays"<<std::endl;
69    }
70
71    virtual void setVertexArray(unsigned int,const Vec2d*)
72    {
73        notify(WARN)<<"Triangle Functor does not support Vec2d* vertex arrays"<<std::endl;
74    }
75
76    virtual void setVertexArray(unsigned int,const Vec3d*)
77    {
78        notify(WARN)<<"Triangle Functor does not support Vec3d* vertex arrays"<<std::endl;
79    }
80
81    virtual void setVertexArray(unsigned int,const Vec4d* )
82    {
83        notify(WARN)<<"Triangle Functor does not support Vec4d* vertex arrays"<<std::endl;
84    }
85
86    virtual void drawArrays(GLenum mode,GLint first,GLsizei count)
87    {
88        if (_vertexArrayPtr==0 || count==0) return;
89
90        switch(mode)
91        {
92            case(GL_TRIANGLES):
93            {
94                const Vec3* vlast = &_vertexArrayPtr[first+count];
95                for(const Vec3* vptr=&_vertexArrayPtr[first];vptr<vlast;vptr+=3)
96                    this->operator()(*(vptr),*(vptr+1),*(vptr+2),_treatVertexDataAsTemporary);
97                break;
98            }
99            case(GL_TRIANGLE_STRIP):
100            {
101                const Vec3* vptr = &_vertexArrayPtr[first];
102                for(GLsizei i=2;i<count;++i,++vptr)
103                {
104                    if ((i%2)) this->operator()(*(vptr),*(vptr+2),*(vptr+1),_treatVertexDataAsTemporary);
105                    else       this->operator()(*(vptr),*(vptr+1),*(vptr+2),_treatVertexDataAsTemporary);
106                }
107                break;
108            }
109            case(GL_QUADS):
110            {
111                const Vec3* vptr = &_vertexArrayPtr[first];
112                for(GLsizei i=3;i<count;i+=4,vptr+=4)
113                {
114                    this->operator()(*(vptr),*(vptr+1),*(vptr+2),_treatVertexDataAsTemporary);
115                    this->operator()(*(vptr),*(vptr+2),*(vptr+3),_treatVertexDataAsTemporary);
116                }
117                break;
118            }
119            case(GL_QUAD_STRIP):
120            {
121                const Vec3* vptr = &_vertexArrayPtr[first];
122                for(GLsizei i=3;i<count;i+=2,vptr+=2)
123                {
124                    this->operator()(*(vptr),*(vptr+1),*(vptr+2),_treatVertexDataAsTemporary);
125                    this->operator()(*(vptr+1),*(vptr+3),*(vptr+2),_treatVertexDataAsTemporary);
126                }
127                break;
128            }
129            case(GL_POLYGON): // treat polygons as GL_TRIANGLE_FAN
130            case(GL_TRIANGLE_FAN):
131            {
132                const Vec3* vfirst = &_vertexArrayPtr[first];
133                const Vec3* vptr = vfirst+1;
134                for(GLsizei i=2;i<count;++i,++vptr)
135                {
136                    this->operator()(*(vfirst),*(vptr),*(vptr+1),_treatVertexDataAsTemporary);
137                }
138                break;
139            }
140            case(GL_POINTS):
141            case(GL_LINES):
142            case(GL_LINE_STRIP):
143            case(GL_LINE_LOOP):
144            default:
145                // can't be converted into to triangles.
146                break;
147        }
148    }
149
150    virtual void drawElements(GLenum mode,GLsizei count,const GLubyte* indices)
151    {
152        if (indices==0 || count==0) return;
153
154        typedef const GLubyte* IndexPointer;
155
156        switch(mode)
157        {
158            case(GL_TRIANGLES):
159            {
160                IndexPointer ilast = &indices[count];
161                for(IndexPointer  iptr=indices;iptr<ilast;iptr+=3)
162                    this->operator()(_vertexArrayPtr[*iptr],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)],_treatVertexDataAsTemporary);
163                break;
164            }
165            case(GL_TRIANGLE_STRIP):
166            {
167                IndexPointer iptr = indices;
168                for(GLsizei i=2;i<count;++i,++iptr)
169                {
170                    if ((i%2)) this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+2)],_vertexArrayPtr[*(iptr+1)],_treatVertexDataAsTemporary);
171                    else       this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)],_treatVertexDataAsTemporary);
172                }
173                break;
174            }
175            case(GL_QUADS):
176            {
177                IndexPointer iptr = indices;
178                for(GLsizei i=3;i<count;i+=4,iptr+=4)
179                {
180                    this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)],_treatVertexDataAsTemporary);
181                    this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+2)],_vertexArrayPtr[*(iptr+3)],_treatVertexDataAsTemporary);
182                }
183                break;
184            }
185            case(GL_QUAD_STRIP):
186            {
187                IndexPointer iptr = indices;
188                for(GLsizei i=3;i<count;i+=2,iptr+=2)
189                {
190                    this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)],_treatVertexDataAsTemporary);
191                    this->operator()(_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+3)],_vertexArrayPtr[*(iptr+2)],_treatVertexDataAsTemporary);
192                }
193                break;
194            }
195            case(GL_POLYGON): // treat polygons as GL_TRIANGLE_FAN
196            case(GL_TRIANGLE_FAN):
197            {
198                IndexPointer iptr = indices;
199                const Vec3& vfirst = _vertexArrayPtr[*iptr];
200                ++iptr;
201                for(GLsizei i=2;i<count;++i,++iptr)
202                {
203                    this->operator()(vfirst,_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_treatVertexDataAsTemporary);
204                }
205                break;
206            }
207            case(GL_POINTS):
208            case(GL_LINES):
209            case(GL_LINE_STRIP):
210            case(GL_LINE_LOOP):
211            default:
212                // can't be converted into to triangles.
213                break;
214        }
215    }
216
217    virtual void drawElements(GLenum mode,GLsizei count,const GLushort* indices)
218    {
219        if (indices==0 || count==0) return;
220
221        typedef const GLushort* IndexPointer;
222
223        switch(mode)
224        {
225            case(GL_TRIANGLES):
226            {
227                IndexPointer ilast = &indices[count];
228                for(IndexPointer  iptr=indices;iptr<ilast;iptr+=3)
229                {
230                    this->operator()(_vertexArrayPtr[*iptr],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)],_treatVertexDataAsTemporary);
231                }
232                break;
233            }
234            case(GL_TRIANGLE_STRIP):
235            {
236                IndexPointer iptr = indices;
237                for(GLsizei i=2;i<count;++i,++iptr)
238                {
239                    if ((i%2)) this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+2)],_vertexArrayPtr[*(iptr+1)],_treatVertexDataAsTemporary);
240                    else       this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)],_treatVertexDataAsTemporary);
241                }
242                break;
243            }
244            case(GL_QUADS):
245            {
246                IndexPointer iptr = indices;
247                for(GLsizei i=3;i<count;i+=4,iptr+=4)
248                {
249                    this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)],_treatVertexDataAsTemporary);
250                    this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+2)],_vertexArrayPtr[*(iptr+3)],_treatVertexDataAsTemporary);
251                }
252                break;
253            }
254            case(GL_QUAD_STRIP):
255            {
256                IndexPointer iptr = indices;
257                for(GLsizei i=3;i<count;i+=2,iptr+=2)
258                {
259                    this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)],_treatVertexDataAsTemporary);
260                    this->operator()(_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+3)],_vertexArrayPtr[*(iptr+2)],_treatVertexDataAsTemporary);
261                }
262                break;
263            }
264            case(GL_POLYGON): // treat polygons as GL_TRIANGLE_FAN
265            case(GL_TRIANGLE_FAN):
266            {
267                IndexPointer iptr = indices;
268                const Vec3& vfirst = _vertexArrayPtr[*iptr];
269                ++iptr;
270                for(GLsizei i=2;i<count;++i,++iptr)
271                {
272                    this->operator()(vfirst,_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_treatVertexDataAsTemporary);
273                }
274                break;
275            }
276            case(GL_POINTS):
277            case(GL_LINES):
278            case(GL_LINE_STRIP):
279            case(GL_LINE_LOOP):
280            default:
281                // can't be converted into to triangles.
282                break;
283        }
284    }
285
286    virtual void drawElements(GLenum mode,GLsizei count,const GLuint* indices)
287    {
288        if (indices==0 || count==0) return;
289
290        typedef const GLuint* IndexPointer;
291
292        switch(mode)
293        {
294            case(GL_TRIANGLES):
295            {
296                IndexPointer ilast = &indices[count];
297                for(IndexPointer  iptr=indices;iptr<ilast;iptr+=3)
298                    this->operator()(_vertexArrayPtr[*iptr],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)],_treatVertexDataAsTemporary);
299                break;
300            }
301            case(GL_TRIANGLE_STRIP):
302            {
303                IndexPointer iptr = indices;
304                for(GLsizei i=2;i<count;++i,++iptr)
305                {
306                    if ((i%2)) this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+2)],_vertexArrayPtr[*(iptr+1)],_treatVertexDataAsTemporary);
307                    else       this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)],_treatVertexDataAsTemporary);
308                }
309                break;
310            }
311            case(GL_QUADS):
312            {
313                IndexPointer iptr = indices;
314                for(GLsizei i=3;i<count;i+=4,iptr+=4)
315                {
316                    this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)],_treatVertexDataAsTemporary);
317                    this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+2)],_vertexArrayPtr[*(iptr+3)],_treatVertexDataAsTemporary);
318                }
319                break;
320            }
321            case(GL_QUAD_STRIP):
322            {
323                IndexPointer iptr = indices;
324                for(GLsizei i=3;i<count;i+=2,iptr+=2)
325                {
326                    this->operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)],_treatVertexDataAsTemporary);
327                    this->operator()(_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+3)],_vertexArrayPtr[*(iptr+2)],_treatVertexDataAsTemporary);
328                }
329                break;
330            }
331            case(GL_POLYGON): // treat polygons as GL_TRIANGLE_FAN
332            case(GL_TRIANGLE_FAN):
333            {
334                IndexPointer iptr = indices;
335                const Vec3& vfirst = _vertexArrayPtr[*iptr];
336                ++iptr;
337                for(GLsizei i=2;i<count;++i,++iptr)
338                {
339                    this->operator()(vfirst,_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_treatVertexDataAsTemporary);
340                }
341                break;
342            }
343            case(GL_POINTS):
344            case(GL_LINES):
345            case(GL_LINE_STRIP):
346            case(GL_LINE_LOOP):
347            default:
348                // can't be converted into to triangles.
349                break;
350        }
351    }
352
353
354
355    /** Note:
356      * begin(..),vertex(..) & end() are convenience methods for adapting
357      * non vertex array primitives to vertex array based primitives.
358      * This is done to simplify the implementation of primitive functor
359      * subclasses - users only need override drawArray and drawElements.
360    */
361    virtual void begin(GLenum mode)
362    {
363        _modeCache = mode;
364        _vertexCache.clear();
365    }
366
367    virtual void vertex(const Vec2& vert) { _vertexCache.push_back(osg::Vec3(vert[0],vert[1],0.0f)); }
368    virtual void vertex(const Vec3& vert) { _vertexCache.push_back(vert); }
369    virtual void vertex(const Vec4& vert) { _vertexCache.push_back(osg::Vec3(vert[0],vert[1],vert[2])/vert[3]); }
370    virtual void vertex(float x,float y) { _vertexCache.push_back(osg::Vec3(x,y,0.0f)); }
371    virtual void vertex(float x,float y,float z) { _vertexCache.push_back(osg::Vec3(x,y,z)); }
372    virtual void vertex(float x,float y,float z,float w) { _vertexCache.push_back(osg::Vec3(x,y,z)/w); }
373    virtual void end()
374    {
375        if (!_vertexCache.empty())
376        {
377            setVertexArray(_vertexCache.size(),&_vertexCache.front());
378            _treatVertexDataAsTemporary = true;
379            drawArrays(_modeCache,0,_vertexCache.size());
380        }
381    }
382
383protected:
384
385
386    unsigned int        _vertexArraySize;
387    const Vec3*         _vertexArrayPtr;
388
389    GLenum              _modeCache;
390    std::vector<Vec3>   _vertexCache;
391    bool                _treatVertexDataAsTemporary;
392};
393
394
395}
396
397#endif
Note: See TracBrowser for help on using the browser.