root/OpenSceneGraph/trunk/src/osg/ShapeDrawable.cpp @ 11472

Revision 11472, 54.3 kB (checked in by robert, 5 years ago)

Convesion of osg::notify to OSG_INFO etc.

  • 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#include <osg/ShapeDrawable>
14#include <osg/GL>
15#include <osg/Notify>
16
17using namespace osg;
18
19// arbitrary minima for rows & segments
20const unsigned int MIN_NUM_ROWS = 3;
21const unsigned int MIN_NUM_SEGMENTS = 5;
22
23
24///////////////////////////////////////////////////////////////////////////////
25//
26// draw shape
27//
28
29class DrawShapeVisitor : public ConstShapeVisitor
30{
31    public:
32   
33        DrawShapeVisitor(State& state,const TessellationHints* hints):
34            _state(state),
35            _hints(hints)
36        {
37#if 0
38            if (hints)
39            {
40                OSG_NOTICE<<"Warning: TessellationHints ignored in present osg::ShapeDrawable implementation."<<std::endl;
41            }
42#endif   
43        }
44   
45        virtual void apply(const Sphere&);
46        virtual void apply(const Box&);
47        virtual void apply(const Cone&);
48        virtual void apply(const Cylinder&);
49        virtual void apply(const Capsule&);
50        virtual void apply(const InfinitePlane&);
51
52        virtual void apply(const TriangleMesh&);
53        virtual void apply(const ConvexHull&);
54        virtual void apply(const HeightField&);
55
56        virtual void apply(const CompositeShape&);
57
58        State&                      _state;
59        const TessellationHints*    _hints;
60       
61    protected:
62
63        DrawShapeVisitor& operator = (const DrawShapeVisitor&) { return *this; }
64
65        enum SphereHalf { SphereTopHalf, SphereBottomHalf };
66   
67        // helpers for apply( Cylinder | Sphere | Capsule )
68        void drawCylinderBody(unsigned int numSegments, float radius, float height);
69        void drawHalfSphere(unsigned int numSegments, unsigned int numRows, float radius, SphereHalf which, float zOffset = 0.0f);
70};
71
72
73void DrawShapeVisitor::drawCylinderBody(unsigned int numSegments, float radius, float height)
74{
75    const float angleDelta = 2.0f*osg::PI/(float)numSegments;
76    const float texCoordDelta = 1.0f/(float)numSegments;
77   
78    const float r = radius;
79    const float h = height;
80   
81    float basez = -h*0.5f;
82    float topz = h*0.5f;
83   
84    float angle = 0.0f;
85    float texCoord = 0.0f;
86   
87    bool drawFrontFace = _hints ? _hints->getCreateFrontFace() : true;
88    bool drawBackFace = _hints ? _hints->getCreateBackFace() : false;
89   
90    // The only difference between the font & back face loops is that the
91    //  normals are inverted and the order of the vertex pairs is reversed.
92    //  The code is mostly duplicated in order to hoist the back/front face
93    //  test out of the loop for efficiency
94
95    GLBeginEndAdapter& gl = _state.getGLBeginEndAdapter();
96
97    gl.Begin(GL_QUAD_STRIP);
98
99    if (drawFrontFace) {
100
101      for(unsigned int bodyi=0;
102          bodyi<numSegments;
103          ++bodyi,angle+=angleDelta,texCoord+=texCoordDelta)
104      {
105          float c = cosf(angle);
106          float s = sinf(angle);
107 
108          gl.Normal3f(c,s,0.0f);
109 
110          gl.TexCoord2f(texCoord,1.0f);
111          gl.Vertex3f(c*r,s*r,topz);
112 
113          gl.TexCoord2f(texCoord,0.0f);
114          gl.Vertex3f(c*r,s*r,basez);
115      }
116 
117      // do last point by hand to ensure no round off errors.
118      gl.Normal3f(1.0f,0.0f,0.0f);
119 
120      gl.TexCoord2f(1.0f,1.0f);
121      gl.Vertex3f(r,0.0f,topz);
122 
123      gl.TexCoord2f(1.0f,0.0f);
124      gl.Vertex3f(r,0.0f,basez);
125    }
126   
127    if (drawBackFace) {
128      for(unsigned int bodyi=0;
129          bodyi<numSegments;
130          ++bodyi,angle+=angleDelta,texCoord+=texCoordDelta)
131      {
132          float c = cosf(angle);
133          float s = sinf(angle);
134 
135          gl.Normal3f(-c,-s,0.0f);
136 
137          gl.TexCoord2f(texCoord,0.0f);
138          gl.Vertex3f(c*r,s*r,basez);
139
140          gl.TexCoord2f(texCoord,1.0f);
141          gl.Vertex3f(c*r,s*r,topz);
142      }
143 
144      // do last point by hand to ensure no round off errors.
145      gl.Normal3f(-1.0f,0.0f,0.0f);
146 
147      gl.TexCoord2f(1.0f,0.0f);
148      gl.Vertex3f(r,0.0f,basez);
149 
150      gl.TexCoord2f(1.0f,1.0f);
151      gl.Vertex3f(r,0.0f,topz);
152    }
153
154    gl.End();
155}
156
157
158void DrawShapeVisitor::drawHalfSphere(unsigned int numSegments, unsigned int numRows, float radius, SphereHalf which, float zOffset)
159{
160    float lDelta = osg::PI/(float)numRows;
161    float vDelta = 1.0f/(float)numRows;
162
163    bool top = (which==SphereTopHalf);
164
165    bool drawFrontFace = _hints ? _hints->getCreateFrontFace() : true;
166    bool drawBackFace = _hints ? _hints->getCreateBackFace() : false;
167
168    float angleDelta = osg::PI*2.0f/(float)numSegments;
169    float texCoordHorzDelta = 1.0f/(float)numSegments;
170
171    float lBase=-osg::PI*0.5f + (top?(lDelta*(numRows/2)):0.0f);
172    float rBase=(top?(cosf(lBase)*radius):0.0f);
173    float zBase=(top?(sinf(lBase)*radius):-radius);
174    float vBase=(top?(vDelta*(numRows/2)):0.0f);
175    float nzBase=(top?(sinf(lBase)):-1.0f);
176    float nRatioBase=(top?(cosf(lBase)):0.0f);
177
178    unsigned int rowbegin = top?numRows/2:0;
179    unsigned int rowend   = top?numRows:numRows/2;
180
181    GLBeginEndAdapter& gl = _state.getGLBeginEndAdapter();
182
183    for(unsigned int rowi=rowbegin; rowi<rowend; ++rowi)
184    {
185
186        float lTop = lBase+lDelta;
187        float rTop = cosf(lTop)*radius;
188        float zTop = sinf(lTop)*radius;
189        float vTop = vBase+vDelta;
190        float nzTop= sinf(lTop);
191        float nRatioTop= cosf(lTop);
192
193        gl.Begin(GL_QUAD_STRIP);
194
195            float angle = 0.0f;
196            float texCoord = 0.0f;
197
198            // The only difference between the font & back face loops is that the
199            //  normals are inverted and the order of the vertex pairs is reversed.
200            //  The code is mostly duplicated in order to hoist the back/front face
201            //  test out of the loop for efficiency
202           
203            if (drawFrontFace) {
204              for(unsigned int topi=0; topi<numSegments;
205                  ++topi,angle+=angleDelta,texCoord+=texCoordHorzDelta)
206              {
207 
208                  float c = cosf(angle);
209                  float s = sinf(angle);
210 
211                  gl.Normal3f(c*nRatioTop,s*nRatioTop,nzTop);
212 
213                  gl.TexCoord2f(texCoord,vTop);
214                  gl.Vertex3f(c*rTop,s*rTop,zTop+zOffset);
215 
216                  gl.Normal3f(c*nRatioBase,s*nRatioBase,nzBase);
217 
218                  gl.TexCoord2f(texCoord,vBase);
219                  gl.Vertex3f(c*rBase,s*rBase,zBase+zOffset);
220 
221              }
222 
223              // do last point by hand to ensure no round off errors.
224              gl.Normal3f(nRatioTop,0.0f,nzTop);
225 
226              gl.TexCoord2f(1.0f,vTop);
227              gl.Vertex3f(rTop,0.0f,zTop+zOffset);
228 
229              gl.Normal3f(nRatioBase,0.0f,nzBase);
230 
231              gl.TexCoord2f(1.0f,vBase);
232              gl.Vertex3f(rBase,0.0f,zBase+zOffset);
233            }
234           
235          if (drawBackFace) {
236              for(unsigned int topi=0; topi<numSegments;
237                  ++topi,angle+=angleDelta,texCoord+=texCoordHorzDelta)
238              {
239 
240                  float c = cosf(angle);
241                  float s = sinf(angle);
242 
243                  gl.Normal3f(-c*nRatioBase,-s*nRatioBase,-nzBase);
244 
245                  gl.TexCoord2f(texCoord,vBase);
246                  gl.Vertex3f(c*rBase,s*rBase,zBase+zOffset);
247 
248                  gl.Normal3f(-c*nRatioTop,-s*nRatioTop,-nzTop);
249 
250                  gl.TexCoord2f(texCoord,vTop);
251                  gl.Vertex3f(c*rTop,s*rTop,zTop+zOffset);
252              }
253 
254              // do last point by hand to ensure no round off errors.
255              gl.Normal3f(-nRatioBase,0.0f,-nzBase);
256 
257              gl.TexCoord2f(1.0f,vBase);
258              gl.Vertex3f(rBase,0.0f,zBase+zOffset);
259
260              gl.Normal3f(-nRatioTop,0.0f,-nzTop);
261 
262              gl.TexCoord2f(1.0f,vTop);
263              gl.Vertex3f(rTop,0.0f,zTop+zOffset);
264 
265          }
266
267        gl.End();
268
269        lBase=lTop;
270        rBase=rTop;
271        zBase=zTop;
272        vBase=vTop;
273        nzBase=nzTop;
274        nRatioBase=nRatioTop;
275
276    }
277}
278
279
280void DrawShapeVisitor::apply(const Sphere& sphere)
281{
282    GLBeginEndAdapter& gl = _state.getGLBeginEndAdapter();
283
284    gl.PushMatrix();
285
286    gl.Translated(sphere.getCenter().x(),sphere.getCenter().y(),sphere.getCenter().z());
287
288    bool drawFrontFace = _hints ? _hints->getCreateFrontFace() : true;
289    bool drawBackFace = _hints ? _hints->getCreateBackFace() : false;
290
291    unsigned int numSegments = 40;
292    unsigned int numRows = 20;
293    float ratio = (_hints ? _hints->getDetailRatio() : 1.0f);
294    if (ratio > 0.0f && ratio != 1.0f) {
295        numRows = (unsigned int) (numRows * ratio);
296        if (numRows < MIN_NUM_ROWS)
297            numRows = MIN_NUM_ROWS;
298        numSegments = (unsigned int) (numSegments * ratio);
299        if (numSegments < MIN_NUM_SEGMENTS)
300            numSegments = MIN_NUM_SEGMENTS;
301    }
302
303    float lDelta = osg::PI/(float)numRows;
304    float vDelta = 1.0f/(float)numRows;
305
306    float angleDelta = osg::PI*2.0f/(float)numSegments;
307    float texCoordHorzDelta = 1.0f/(float)numSegments;
308
309    gl.Begin(GL_QUAD_STRIP);
310
311    if (drawBackFace)
312    {
313        float lBase=-osg::PI*0.5f;
314        float rBase=0.0f;
315        float zBase=-sphere.getRadius();
316        float vBase=0.0f;
317        float nzBase=-1.0f;
318        float nRatioBase=0.0f;
319
320        for(unsigned int rowi=0; rowi<numRows; ++rowi)
321        {
322
323            float lTop = lBase+lDelta;
324            float rTop = cosf(lTop)*sphere.getRadius();
325            float zTop = sinf(lTop)*sphere.getRadius();
326            float vTop = vBase+vDelta;
327            float nzTop= sinf(lTop);
328            float nRatioTop= cosf(lTop);
329
330            gl.Begin(GL_QUAD_STRIP);
331
332                float angle = 0.0f;
333                float texCoord = 0.0f;
334
335                for(unsigned int topi=0; topi<numSegments;
336                    ++topi,angle+=angleDelta,texCoord+=texCoordHorzDelta)
337                {
338
339                    float c = cosf(angle);
340                    float s = sinf(angle);
341
342                    gl.Normal3f(-c*nRatioBase,-s*nRatioBase,-nzBase);
343
344                    gl.TexCoord2f(texCoord,vBase);
345                    gl.Vertex3f(c*rBase,s*rBase,zBase);
346
347                    gl.Normal3f(-c*nRatioTop,-s*nRatioTop,-nzTop);
348
349                    gl.TexCoord2f(texCoord,vTop);
350                    gl.Vertex3f(c*rTop,s*rTop,zTop);
351
352
353                }
354
355
356                // do last point by hand to ensure no round off errors.
357                gl.Normal3f(-nRatioBase,0.0f,-nzBase);
358
359                gl.TexCoord2f(1.0f,vBase);
360                gl.Vertex3f(rBase,0.0f,zBase);
361
362                gl.Normal3f(-nRatioTop,0.0f,-nzTop);
363
364                gl.TexCoord2f(1.0f,vTop);
365                gl.Vertex3f(rTop,0.0f,zTop);
366
367            gl.End();
368
369
370            lBase=lTop;
371            rBase=rTop;
372            zBase=zTop;
373            vBase=vTop;
374            nzBase=nzTop;
375            nRatioBase=nRatioTop;
376
377        }
378    }
379
380
381    if (drawFrontFace)
382    {
383        float lBase=-osg::PI*0.5f;
384        float rBase=0.0f;
385        float zBase=-sphere.getRadius();
386        float vBase=0.0f;
387        float nzBase=-1.0f;
388        float nRatioBase=0.0f;
389
390        for(unsigned int rowi=0; rowi<numRows; ++rowi)
391        {
392
393            float lTop = lBase+lDelta;
394            float rTop = cosf(lTop)*sphere.getRadius();
395            float zTop = sinf(lTop)*sphere.getRadius();
396            float vTop = vBase+vDelta;
397            float nzTop= sinf(lTop);
398            float nRatioTop= cosf(lTop);
399
400            gl.Begin(GL_QUAD_STRIP);
401
402                float angle = 0.0f;
403                float texCoord = 0.0f;
404
405                for(unsigned int topi=0; topi<numSegments;
406                    ++topi,angle+=angleDelta,texCoord+=texCoordHorzDelta)
407                {
408
409                    float c = cosf(angle);
410                    float s = sinf(angle);
411
412                    gl.Normal3f(c*nRatioTop,s*nRatioTop,nzTop);
413
414                    gl.TexCoord2f(texCoord,vTop);
415                    gl.Vertex3f(c*rTop,s*rTop,zTop);
416
417                    gl.Normal3f(c*nRatioBase,s*nRatioBase,nzBase);
418
419                    gl.TexCoord2f(texCoord,vBase);
420                    gl.Vertex3f(c*rBase,s*rBase,zBase);
421
422                }
423
424                // do last point by hand to ensure no round off errors.
425                gl.Normal3f(nRatioTop,0.0f,nzTop);
426
427                gl.TexCoord2f(1.0f,vTop);
428                gl.Vertex3f(rTop,0.0f,zTop);
429
430                gl.Normal3f(nRatioBase,0.0f,nzBase);
431
432                gl.TexCoord2f(1.0f,vBase);
433                gl.Vertex3f(rBase,0.0f,zBase);
434
435            gl.End();
436
437
438            lBase=lTop;
439            rBase=rTop;
440            zBase=zTop;
441            vBase=vTop;
442            nzBase=nzTop;
443            nRatioBase=nRatioTop;
444
445        }
446    }
447
448    gl.PopMatrix();
449}
450
451void DrawShapeVisitor::apply(const Box& box)
452{
453    GLBeginEndAdapter& gl = _state.getGLBeginEndAdapter();
454
455    // evaluate hints
456    bool createBody = (_hints ? _hints->getCreateBody() : true);
457    bool createTop = (_hints ? _hints->getCreateTop() : true);
458    bool createBottom = (_hints ? _hints->getCreateBottom() : true);
459
460    float dx = box.getHalfLengths().x();
461    float dy = box.getHalfLengths().y();
462    float dz = box.getHalfLengths().z();
463
464    gl.PushMatrix();
465
466    gl.Translated(box.getCenter().x(),box.getCenter().y(),box.getCenter().z());
467
468    if (!box.zeroRotation())
469    {
470        Matrixd rotation(box.computeRotationMatrix());
471        gl.MultMatrixd(rotation.ptr());
472    }
473
474    gl.Begin(GL_QUADS);
475
476    if (createBody) {
477        // -ve y plane
478        gl.Normal3f(0.0f,-1.0f,0.0f);
479
480        gl.TexCoord2f(0.0f,1.0f);
481        gl.Vertex3f(-dx,-dy,dz);
482
483        gl.TexCoord2f(0.0f,0.0f);
484        gl.Vertex3f(-dx,-dy,-dz);
485
486        gl.TexCoord2f(1.0f,0.0f);
487        gl.Vertex3f(dx,-dy,-dz);
488
489        gl.TexCoord2f(1.0f,1.0f);
490        gl.Vertex3f(dx,-dy,dz);
491
492        // +ve y plane
493        gl.Normal3f(0.0f,1.0f,0.0f);
494
495        gl.TexCoord2f(0.0f,1.0f);
496        gl.Vertex3f(dx,dy,dz);
497
498        gl.TexCoord2f(0.0f,0.0f);
499        gl.Vertex3f(dx,dy,-dz);
500
501        gl.TexCoord2f(1.0f,0.0f);
502        gl.Vertex3f(-dx,dy,-dz);
503
504        gl.TexCoord2f(1.0f,1.0f);
505        gl.Vertex3f(-dx,dy,dz);
506
507        // +ve x plane
508        gl.Normal3f(1.0f,0.0f,0.0f);
509
510        gl.TexCoord2f(0.0f,1.0f);
511        gl.Vertex3f(dx,-dy,dz);
512
513        gl.TexCoord2f(0.0f,0.0f);
514        gl.Vertex3f(dx,-dy,-dz);
515
516        gl.TexCoord2f(1.0f,0.0f);
517        gl.Vertex3f(dx,dy,-dz);
518
519        gl.TexCoord2f(1.0f,1.0f);
520        gl.Vertex3f(dx,dy,dz);
521
522        // -ve x plane
523        gl.Normal3f(-1.0f,0.0f,0.0f);
524
525        gl.TexCoord2f(0.0f,1.0f);
526        gl.Vertex3f(-dx,dy,dz);
527
528        gl.TexCoord2f(0.0f,0.0f);
529        gl.Vertex3f(-dx,dy,-dz);
530
531        gl.TexCoord2f(1.0f,0.0f);
532        gl.Vertex3f(-dx,-dy,-dz);
533
534        gl.TexCoord2f(1.0f,1.0f);
535        gl.Vertex3f(-dx,-dy,dz);
536    }
537
538    if (createTop) {
539        // +ve z plane
540        gl.Normal3f(0.0f,0.0f,1.0f);
541
542        gl.TexCoord2f(0.0f,1.0f);
543        gl.Vertex3f(-dx,dy,dz);
544
545        gl.TexCoord2f(0.0f,0.0f);
546        gl.Vertex3f(-dx,-dy,dz);
547
548        gl.TexCoord2f(1.0f,0.0f);
549        gl.Vertex3f(dx,-dy,dz);
550
551        gl.TexCoord2f(1.0f,1.0f);
552        gl.Vertex3f(dx,dy,dz);
553    }
554
555    if (createBottom) {
556        // -ve z plane
557        gl.Normal3f(0.0f,0.0f,-1.0f);
558
559        gl.TexCoord2f(0.0f,1.0f);
560        gl.Vertex3f(dx,dy,-dz);
561
562        gl.TexCoord2f(0.0f,0.0f);
563        gl.Vertex3f(dx,-dy,-dz);
564
565        gl.TexCoord2f(1.0f,0.0f);
566        gl.Vertex3f(-dx,-dy,-dz);
567
568        gl.TexCoord2f(1.0f,1.0f);
569        gl.Vertex3f(-dx,dy,-dz);
570    }
571
572    gl.End();
573
574    gl.PopMatrix();
575
576}
577
578void DrawShapeVisitor::apply(const Cone& cone)
579{
580    GLBeginEndAdapter& gl = _state.getGLBeginEndAdapter();
581
582    gl.PushMatrix();
583
584    gl.Translated(cone.getCenter().x(),cone.getCenter().y(),cone.getCenter().z());
585
586    if (!cone.zeroRotation())
587    {
588        Matrixd rotation(cone.computeRotationMatrix());
589        gl.MultMatrixd(rotation.ptr());
590    }
591
592    // evaluate hints
593    bool createBody = (_hints ? _hints->getCreateBody() : true);
594    bool createBottom = (_hints ? _hints->getCreateBottom() : true);
595
596    unsigned int numSegments = 40;
597    unsigned int numRows = 10;
598    float ratio = (_hints ? _hints->getDetailRatio() : 1.0f);
599    if (ratio > 0.0f && ratio != 1.0f) {
600        numRows = (unsigned int) (numRows * ratio);
601        if (numRows < MIN_NUM_ROWS)
602            numRows = MIN_NUM_ROWS;
603        numSegments = (unsigned int) (numSegments * ratio);
604        if (numSegments < MIN_NUM_SEGMENTS)
605            numSegments = MIN_NUM_SEGMENTS;
606    }
607
608    float r = cone.getRadius();
609    float h = cone.getHeight();
610
611    float normalz = r/(sqrtf(r*r+h*h));
612    float normalRatio = 1.0f/(sqrtf(1.0f+normalz*normalz));
613    normalz *= normalRatio;
614
615    float angleDelta = 2.0f*osg::PI/(float)numSegments;
616    float texCoordHorzDelta = 1.0/(float)numSegments;
617    float texCoordRowDelta = 1.0/(float)numRows;
618    float hDelta = cone.getHeight()/(float)numRows;
619    float rDelta = cone.getRadius()/(float)numRows;
620
621    float topz=cone.getHeight()+cone.getBaseOffset();
622    float topr=0.0f;
623    float topv=1.0f;
624    float basez=topz-hDelta;
625    float baser=rDelta;
626    float basev=topv-texCoordRowDelta;
627    float angle;
628    float texCoord;
629
630    if (createBody) {
631        for(unsigned int rowi=0; rowi<numRows;
632            ++rowi,topz=basez, basez-=hDelta, topr=baser, baser+=rDelta, topv=basev, basev-=texCoordRowDelta) {
633                // we can't use a fan for the cone top
634                // since we need different normals at the top
635                // for each face..
636                gl.Begin(GL_QUAD_STRIP);
637
638                angle = 0.0f;
639                texCoord = 0.0f;
640                for(unsigned int topi=0; topi<numSegments;
641                    ++topi,angle+=angleDelta,texCoord+=texCoordHorzDelta) {
642
643                    float c = cosf(angle);
644                    float s = sinf(angle);
645
646                    gl.Normal3f(c*normalRatio,s*normalRatio,normalz);
647
648                    gl.TexCoord2f(texCoord,topv);
649                    gl.Vertex3f(c*topr,s*topr,topz);
650
651                    gl.TexCoord2f(texCoord,basev);
652                    gl.Vertex3f(c*baser,s*baser,basez);
653                }
654
655                // do last point by hand to ensure no round off errors.
656                gl.Normal3f(normalRatio,0.0f,normalz);
657
658                gl.TexCoord2f(1.0f,topv);
659                gl.Vertex3f(topr,0.0f,topz);
660
661                gl.TexCoord2f(1.0f,basev);
662                gl.Vertex3f(baser,0.0f,basez);
663
664                gl.End();
665        }
666    }
667
668    if (createBottom) {
669        gl.Begin(GL_TRIANGLE_FAN);
670
671        angle = osg::PI*2.0f;
672        texCoord = 1.0f;
673        basez = cone.getBaseOffset();
674
675        gl.Normal3f(0.0f,0.0f,-1.0f);
676        gl.TexCoord2f(0.5f,0.5f);
677        gl.Vertex3f(0.0f,0.0f,basez);
678
679        for(unsigned int bottomi=0;bottomi<numSegments;
680            ++bottomi,angle-=angleDelta,texCoord-=texCoordHorzDelta) {
681
682            float c = cosf(angle);
683            float s = sinf(angle);
684
685            gl.TexCoord2f(c*0.5f+0.5f,s*0.5f+0.5f);
686            gl.Vertex3f(c*r,s*r,basez);
687        }
688
689        gl.TexCoord2f(1.0f,0.0f);
690        gl.Vertex3f(r,0.0f,basez);
691
692        gl.End();
693    }
694
695    gl.PopMatrix();
696}
697
698void DrawShapeVisitor::apply(const Cylinder& cylinder)
699{
700    GLBeginEndAdapter& gl = _state.getGLBeginEndAdapter();
701
702    gl.PushMatrix();
703
704    gl.Translated(cylinder.getCenter().x(),cylinder.getCenter().y(),cylinder.getCenter().z());
705
706    if (!cylinder.zeroRotation())
707    {
708        Matrixd rotation(cylinder.computeRotationMatrix());
709        gl.MultMatrixd(rotation.ptr());
710    }
711
712    // evaluate hints
713    bool createBody = (_hints ? _hints->getCreateBody() : true);
714    bool createTop = (_hints ? _hints->getCreateTop() : true);
715    bool createBottom = (_hints ? _hints->getCreateBottom() : true);
716
717    unsigned int numSegments = 40;
718    float ratio = (_hints ? _hints->getDetailRatio() : 1.0f);
719    if (ratio > 0.0f && ratio != 1.0f) {
720        numSegments = (unsigned int) (numSegments * ratio);
721        if (numSegments < MIN_NUM_SEGMENTS)
722            numSegments = MIN_NUM_SEGMENTS;
723    }
724
725
726    // cylinder body
727    if (createBody)
728        drawCylinderBody(numSegments, cylinder.getRadius(), cylinder.getHeight());
729
730    float angleDelta = 2.0f*osg::PI/(float)numSegments;
731    float texCoordDelta = 1.0f/(float)numSegments;
732
733    float r = cylinder.getRadius();
734    float h = cylinder.getHeight();
735
736    float basez = -h*0.5f;
737    float topz = h*0.5f;
738
739    float angle = 0.0f;
740    float texCoord = 0.0f;
741
742    // cylinder top
743    if (createTop) {
744        gl.Begin(GL_TRIANGLE_FAN);
745
746        gl.Normal3f(0.0f,0.0f,1.0f);
747        gl.TexCoord2f(0.5f,0.5f);
748        gl.Vertex3f(0.0f,0.0f,topz);
749
750        angle = 0.0f;
751        texCoord = 0.0f;
752        for(unsigned int topi=0;
753            topi<numSegments;
754            ++topi,angle+=angleDelta,texCoord+=texCoordDelta)
755        {
756            float c = cosf(angle);
757            float s = sinf(angle);
758
759            gl.TexCoord2f(c*0.5f+0.5f,s*0.5f+0.5f);
760            gl.Vertex3f(c*r,s*r,topz);
761        }
762
763        gl.TexCoord2f(1.0f,0.5f);
764        gl.Vertex3f(r,0.0f,topz);
765
766        gl.End();
767    }
768
769    // cylinder bottom
770    if (createBottom)
771    {
772        gl.Begin(GL_TRIANGLE_FAN);
773
774        gl.Normal3f(0.0f,0.0f,-1.0f);
775        gl.TexCoord2f(0.5f,0.5f);
776        gl.Vertex3f(0.0f,0.0f,basez);
777
778        angle = osg::PI*2.0f;
779        texCoord = 1.0f;
780        for(unsigned int bottomi=0;
781            bottomi<numSegments;
782            ++bottomi,angle-=angleDelta,texCoord-=texCoordDelta)
783        {
784            float c = cosf(angle);
785            float s = sinf(angle);
786
787            gl.TexCoord2f(c*0.5f+0.5f,s*0.5f+0.5f);
788            gl.Vertex3f(c*r,s*r,basez);
789        }
790
791        gl.TexCoord2f(1.0f,0.5f);
792        gl.Vertex3f(r,0.0f,basez);
793
794        gl.End();
795    }
796
797    gl.PopMatrix();
798}
799
800void DrawShapeVisitor::apply(const Capsule& capsule)
801{
802    GLBeginEndAdapter& gl = _state.getGLBeginEndAdapter();
803
804    gl.PushMatrix();
805
806    gl.Translated(capsule.getCenter().x(),capsule.getCenter().y(),capsule.getCenter().z());
807
808    if (!capsule.zeroRotation())
809    {
810        Matrixd rotation(capsule.computeRotationMatrix());
811        gl.MultMatrixd(rotation.ptr());
812    }
813
814    // evaluate hints
815    bool createBody = (_hints ? _hints->getCreateBody() : true);
816    bool createTop = (_hints ? _hints->getCreateTop() : true);
817    bool createBottom = (_hints ? _hints->getCreateBottom() : true);
818
819    unsigned int numSegments = 40;
820    unsigned int numRows = 20;
821    float ratio = (_hints ? _hints->getDetailRatio() : 1.0f);
822    if (ratio > 0.0f && ratio != 1.0f) {
823        numSegments = (unsigned int) (numSegments * ratio);
824        if (numSegments < MIN_NUM_SEGMENTS)
825            numSegments = MIN_NUM_SEGMENTS;
826        numRows = (unsigned int) (numRows * ratio);
827        if (numRows < MIN_NUM_ROWS)
828            numRows = MIN_NUM_ROWS;
829    }
830
831
832    // capsule cylindrical body
833    if (createBody)
834        drawCylinderBody(numSegments, capsule.getRadius(), capsule.getHeight());
835
836    // capsule top cap
837    if (createTop)
838        drawHalfSphere(numSegments, numRows, capsule.getRadius(), SphereTopHalf, capsule.getHeight()/2.0f);
839
840    // capsule bottom cap
841    if (createBottom)
842        drawHalfSphere(numSegments, numRows, capsule.getRadius(), SphereBottomHalf, -capsule.getHeight()/2.0f);
843
844    gl.PopMatrix();
845}
846
847void DrawShapeVisitor::apply(const InfinitePlane&)
848{
849    OSG_NOTICE<<"Warning: DrawShapeVisitor::apply(const InfinitePlane& plane) not yet implemented. "<<std::endl;
850}
851
852void DrawShapeVisitor::apply(const TriangleMesh& mesh)
853{
854    GLBeginEndAdapter& gl = _state.getGLBeginEndAdapter();
855
856    const Vec3Array* vertices = mesh.getVertices();
857    const IndexArray* indices = mesh.getIndices();
858   
859     if (vertices && indices)
860     {
861        gl.Begin(GL_TRIANGLES);
862
863        for(unsigned int i=0;i+2<indices->getNumElements();i+=3)
864        {
865            const osg::Vec3& v1=(*vertices)[indices->index(i)];
866            const osg::Vec3& v2=(*vertices)[indices->index(i+1)];
867            const osg::Vec3& v3=(*vertices)[indices->index(i+2)];
868            Vec3 normal = (v2-v1)^(v3-v2);
869            normal.normalize();
870
871            gl.Normal3fv(normal.ptr());
872            gl.Vertex3fv(v1.ptr());
873            gl.Vertex3fv(v2.ptr());
874            gl.Vertex3fv(v3.ptr());
875
876        }
877
878        gl.End();
879    }
880}
881
882void DrawShapeVisitor::apply(const ConvexHull& hull)
883{
884    apply((const TriangleMesh&)hull);
885}
886
887void DrawShapeVisitor::apply(const HeightField& field)
888{
889    if (field.getNumColumns()==0 || field.getNumRows()==0) return;
890
891    GLBeginEndAdapter& gl = _state.getGLBeginEndAdapter();
892
893    gl.PushMatrix();
894
895    gl.Translated(field.getOrigin().x(),field.getOrigin().y(),field.getOrigin().z());
896
897
898    if (!field.zeroRotation())
899    {
900        Matrixd rotation(field.computeRotationMatrix());
901        gl.MultMatrixd(rotation.ptr());
902    }
903
904    float dx = field.getXInterval();
905    float dy = field.getYInterval();
906
907    float du = 1.0f/((float)field.getNumColumns()-1.0f);
908    float dv = 1.0f/((float)field.getNumRows()-1.0f);
909
910    float vBase = 0.0f;
911
912    Vec3 vertTop;
913    Vec3 normTop;
914
915    Vec3 vertBase;
916    Vec3 normBase;
917
918    if (field.getSkirtHeight()!=0.0f)
919    {
920        gl.Begin(GL_QUAD_STRIP);
921
922        float u = 0.0f;
923
924        // draw bottom skirt
925        unsigned int col;
926        vertTop.y() = 0.0f;
927        for(col=0;col<field.getNumColumns();++col,u+=du)
928        {
929            vertTop.x() = dx*(float)col;
930            vertTop.z() = field.getHeight(col,0);
931            normTop.set(field.getNormal(col,0));
932
933            gl.TexCoord2f(u,0.0f);
934            gl.Normal3fv(normTop.ptr());
935
936            gl.Vertex3fv(vertTop.ptr());
937
938            vertTop.z()-=field.getSkirtHeight();
939
940            gl.Vertex3fv(vertTop.ptr());
941        }
942
943        gl.End();
944
945        // draw top skirt
946        gl.Begin(GL_QUAD_STRIP);
947
948        unsigned int row = field.getNumRows()-1;
949
950        u = 0.0f;
951        vertTop.y() = dy*(float)(row);
952        for(col=0;col<field.getNumColumns();++col,u+=du)
953        {
954            vertTop.x() = dx*(float)col;
955            vertTop.z() = field.getHeight(col,row);
956            normTop.set(field.getNormal(col,row));
957
958            gl.TexCoord2f(u,1.0f);
959            gl.Normal3fv(normTop.ptr());
960
961            gl.Vertex3f(vertTop.x(),vertTop.y(),vertTop.z()-field.getSkirtHeight());
962
963            //vertTop.z()-=field.getSkirtHeight();
964
965            gl.Vertex3fv(vertTop.ptr());
966        }
967
968        gl.End();
969    }
970
971
972
973    // draw each row of HeightField
974    for(unsigned int row=0;row<field.getNumRows()-1;++row,vBase+=dv)
975    {
976
977        float vTop = vBase+dv;
978        float u = 0.0f;
979
980
981        gl.Begin(GL_QUAD_STRIP);
982
983        // draw skirt at beginning of this row if required.
984        if (field.getSkirtHeight()!=0.0f)
985        {
986            vertTop.set(0.0f,dy*(float)(row+1),field.getHeight(0,row+1)-field.getSkirtHeight());
987            normTop.set(field.getNormal(0,row+1));
988
989            vertBase.set(0.0f,dy*(float)row,field.getHeight(0,row)-field.getSkirtHeight());
990            normBase.set(field.getNormal(0,row));
991
992            gl.TexCoord2f(u,vTop);
993            gl.Normal3fv(normTop.ptr());
994            gl.Vertex3fv(vertTop.ptr());
995
996            gl.TexCoord2f(u,vBase);
997            gl.Normal3fv(normBase.ptr());
998            gl.Vertex3fv(vertBase.ptr());
999        }
1000
1001        // draw the actual row
1002        for(unsigned int col=0;col<field.getNumColumns();++col,u+=du)
1003        {
1004            vertTop.set(dx*(float)col,dy*(float)(row+1),field.getHeight(col,row+1));
1005            normTop.set(field.getNormal(col,row+1));
1006
1007            vertBase.set(dx*(float)col,dy*(float)row,field.getHeight(col,row));
1008            normBase.set(field.getNormal(col,row));
1009
1010            gl.TexCoord2f(u,vTop);
1011            gl.Normal3fv(normTop.ptr());
1012            gl.Vertex3fv(vertTop.ptr());
1013
1014            gl.TexCoord2f(u,vBase);
1015            gl.Normal3fv(normBase.ptr());
1016            gl.Vertex3fv(vertBase.ptr());
1017
1018        }
1019
1020        // draw skirt at end of this row if required.
1021        if (field.getSkirtHeight()!=0.0f)
1022        {
1023
1024            vertBase.z()-=field.getSkirtHeight();
1025            vertTop.z()-=field.getSkirtHeight();
1026
1027            gl.TexCoord2f(u,vTop);
1028            gl.Normal3fv(normTop.ptr());
1029            gl.Vertex3fv(vertTop.ptr());
1030
1031            gl.TexCoord2f(u,vBase);
1032            gl.Normal3fv(normBase.ptr());
1033            gl.Vertex3fv(vertBase.ptr());
1034        }
1035
1036        gl.End();
1037    }
1038
1039
1040    gl.PopMatrix();
1041
1042}
1043
1044void DrawShapeVisitor::apply(const CompositeShape& group)
1045{
1046    for(unsigned int i=0;i<group.getNumChildren();++i)
1047    {
1048        group.getChild(i)->accept(*this);
1049    }
1050}
1051
1052
1053
1054
1055///////////////////////////////////////////////////////////////////////////////
1056//
1057// Compute bounding of shape
1058//
1059
1060class ComputeBoundShapeVisitor : public ConstShapeVisitor
1061{
1062    public:
1063   
1064        ComputeBoundShapeVisitor(BoundingBox& bb):_bb(bb) {}
1065
1066        virtual void apply(const Sphere&);
1067        virtual void apply(const Box&);
1068        virtual void apply(const Cone&);
1069        virtual void apply(const Cylinder&);
1070        virtual void apply(const Capsule&);
1071        virtual void apply(const InfinitePlane&);
1072
1073        virtual void apply(const TriangleMesh&);
1074        virtual void apply(const ConvexHull&);
1075        virtual void apply(const HeightField&);
1076
1077        virtual void apply(const CompositeShape&);
1078
1079        BoundingBox&    _bb;
1080
1081    protected:
1082
1083        ComputeBoundShapeVisitor& operator = (const ComputeBoundShapeVisitor&) { return *this; }
1084
1085};
1086
1087
1088void ComputeBoundShapeVisitor::apply(const Sphere& sphere)
1089{
1090    Vec3 halfLengths(sphere.getRadius(),sphere.getRadius(),sphere.getRadius());
1091    _bb.expandBy(sphere.getCenter()-halfLengths);
1092    _bb.expandBy(sphere.getCenter()+halfLengths);
1093}
1094
1095void ComputeBoundShapeVisitor::apply(const Box& box)
1096{
1097    if (box.zeroRotation())
1098    {
1099        _bb.expandBy(box.getCenter()-box.getHalfLengths());
1100        _bb.expandBy(box.getCenter()+box.getHalfLengths());
1101    }
1102    else
1103    {
1104        float x = box.getHalfLengths().x();
1105        float y = box.getHalfLengths().y();
1106        float z = box.getHalfLengths().z();
1107
1108        Vec3 base_1(Vec3(-x,-y,-z));
1109        Vec3 base_2(Vec3(x,-y,-z));
1110        Vec3 base_3(Vec3(x,y,-z));
1111        Vec3 base_4(Vec3(-x,y,-z));
1112
1113        Vec3 top_1(Vec3(-x,-y,z));
1114        Vec3 top_2(Vec3(x,-y,z));
1115        Vec3 top_3(Vec3(x,y,z));
1116        Vec3 top_4(Vec3(-x,y,z));
1117
1118        Matrix matrix = box.computeRotationMatrix();
1119        _bb.expandBy(box.getCenter()+base_1*matrix);
1120        _bb.expandBy(box.getCenter()+base_2*matrix);
1121        _bb.expandBy(box.getCenter()+base_3*matrix);
1122        _bb.expandBy(box.getCenter()+base_4*matrix);
1123
1124        _bb.expandBy(box.getCenter()+top_1*matrix);
1125        _bb.expandBy(box.getCenter()+top_2*matrix);
1126        _bb.expandBy(box.getCenter()+top_3*matrix);
1127        _bb.expandBy(box.getCenter()+top_4*matrix);
1128    }
1129}
1130
1131void ComputeBoundShapeVisitor::apply(const Cone& cone)
1132{
1133    if (cone.zeroRotation())
1134    {
1135        _bb.expandBy(cone.getCenter()+Vec3(-cone.getRadius(),-cone.getRadius(),cone.getBaseOffset()));
1136        _bb.expandBy(cone.getCenter()+Vec3(cone.getRadius(),cone.getRadius(),cone.getHeight()+cone.getBaseOffset()));
1137
1138    }
1139    else
1140    {
1141        Vec3 top(Vec3(cone.getRadius(),cone.getRadius(),cone.getHeight()+cone.getBaseOffset()));
1142        Vec3 base_1(Vec3(-cone.getRadius(),-cone.getRadius(),cone.getBaseOffset()));
1143        Vec3 base_2(Vec3(cone.getRadius(),-cone.getRadius(),cone.getBaseOffset()));
1144        Vec3 base_3(Vec3(cone.getRadius(),cone.getRadius(),cone.getBaseOffset()));
1145        Vec3 base_4(Vec3(-cone.getRadius(),cone.getRadius(),cone.getBaseOffset()));
1146
1147        Matrix matrix = cone.computeRotationMatrix();
1148        _bb.expandBy(cone.getCenter()+base_1*matrix);
1149        _bb.expandBy(cone.getCenter()+base_2*matrix);
1150        _bb.expandBy(cone.getCenter()+base_3*matrix);
1151        _bb.expandBy(cone.getCenter()+base_4*matrix);
1152        _bb.expandBy(cone.getCenter()+top*matrix);
1153    }
1154}
1155
1156void ComputeBoundShapeVisitor::apply(const Cylinder& cylinder)
1157{
1158    if (cylinder.zeroRotation())
1159    {
1160        Vec3 halfLengths(cylinder.getRadius(),cylinder.getRadius(),cylinder.getHeight()*0.5f);
1161        _bb.expandBy(cylinder.getCenter()-halfLengths);
1162        _bb.expandBy(cylinder.getCenter()+halfLengths);
1163
1164    }
1165    else
1166    {
1167        float r = cylinder.getRadius();
1168        float z = cylinder.getHeight()*0.5f;
1169
1170        Vec3 base_1(Vec3(-r,-r,-z));
1171        Vec3 base_2(Vec3(r,-r,-z));
1172        Vec3 base_3(Vec3(r,r,-z));
1173        Vec3 base_4(Vec3(-r,r,-z));
1174
1175        Vec3 top_1(Vec3(-r,-r,z));
1176        Vec3 top_2(Vec3(r,-r,z));
1177        Vec3 top_3(Vec3(r,r,z));
1178        Vec3 top_4(Vec3(-r,r,z));
1179
1180        Matrix matrix = cylinder.computeRotationMatrix();
1181        _bb.expandBy(cylinder.getCenter()+base_1*matrix);
1182        _bb.expandBy(cylinder.getCenter()+base_2*matrix);
1183        _bb.expandBy(cylinder.getCenter()+base_3*matrix);
1184        _bb.expandBy(cylinder.getCenter()+base_4*matrix);
1185
1186        _bb.expandBy(cylinder.getCenter()+top_1*matrix);
1187        _bb.expandBy(cylinder.getCenter()+top_2*matrix);
1188        _bb.expandBy(cylinder.getCenter()+top_3*matrix);
1189        _bb.expandBy(cylinder.getCenter()+top_4*matrix);
1190    }
1191}
1192
1193void ComputeBoundShapeVisitor::apply(const Capsule& capsule)
1194{
1195    if (capsule.zeroRotation())
1196    {
1197        Vec3 halfLengths(capsule.getRadius(),capsule.getRadius(),capsule.getHeight()*0.5f + capsule.getRadius());
1198        _bb.expandBy(capsule.getCenter()-halfLengths);
1199        _bb.expandBy(capsule.getCenter()+halfLengths);
1200
1201    }
1202    else
1203    {
1204        float r = capsule.getRadius();
1205        float z = capsule.getHeight()*0.5f + capsule.getRadius();
1206
1207        Vec3 base_1(Vec3(-r,-r,-z));
1208        Vec3 base_2(Vec3(r,-r,-z));
1209        Vec3 base_3(Vec3(r,r,-z));
1210        Vec3 base_4(Vec3(-r,r,-z));
1211
1212        Vec3 top_1(Vec3(-r,-r,z));
1213        Vec3 top_2(Vec3(r,-r,z));
1214        Vec3 top_3(Vec3(r,r,z));
1215        Vec3 top_4(Vec3(-r,r,z));
1216
1217        Matrix matrix = capsule.computeRotationMatrix();
1218        _bb.expandBy(capsule.getCenter()+base_1*matrix);
1219        _bb.expandBy(capsule.getCenter()+base_2*matrix);
1220        _bb.expandBy(capsule.getCenter()+base_3*matrix);
1221        _bb.expandBy(capsule.getCenter()+base_4*matrix);
1222
1223        _bb.expandBy(capsule.getCenter()+top_1*matrix);
1224        _bb.expandBy(capsule.getCenter()+top_2*matrix);
1225        _bb.expandBy(capsule.getCenter()+top_3*matrix);
1226        _bb.expandBy(capsule.getCenter()+top_4*matrix);
1227    }
1228}
1229
1230void ComputeBoundShapeVisitor::apply(const InfinitePlane&)
1231{
1232    // can't compute the bounding box of an infinite plane!!! :-)
1233}
1234
1235void ComputeBoundShapeVisitor::apply(const TriangleMesh& mesh)
1236{
1237    const Vec3Array* vertices = mesh.getVertices();
1238    const IndexArray* indices = mesh.getIndices();
1239   
1240    if (vertices && indices)
1241    {
1242        for(unsigned int i=0;i<indices->getNumElements();++i)
1243        {
1244            const osg::Vec3& v=(*vertices)[indices->index(i)];
1245            _bb.expandBy(v);
1246        }
1247    }
1248}
1249
1250void ComputeBoundShapeVisitor::apply(const ConvexHull& hull)
1251{
1252    apply((const TriangleMesh&)hull);
1253}
1254
1255void ComputeBoundShapeVisitor::apply(const HeightField& field)
1256{
1257    float zMin=FLT_MAX;
1258    float zMax=-FLT_MAX;
1259
1260    for(unsigned int row=0;row<field.getNumRows();++row)
1261    {
1262        for(unsigned int col=0;col<field.getNumColumns();++col)
1263        {
1264            float z = field.getHeight(col,row);
1265            if (z<zMin) zMin = z;
1266            if (z>zMax) zMax = z;
1267        }
1268    }
1269
1270    if (zMin>zMax)
1271    {
1272        // no valid entries so don't reset the bounding box
1273        return;
1274    }
1275
1276
1277    if (field.zeroRotation())
1278    {
1279        _bb.expandBy(field.getOrigin()+osg::Vec3(0.0f,0.0f,zMin));
1280        _bb.expandBy(field.getOrigin()+osg::Vec3(field.getXInterval()*(field.getNumColumns()-1),field.getYInterval()*(field.getNumRows()-1),zMax));
1281    }
1282    else
1283    {
1284        float x = field.getXInterval()*(field.getNumColumns()-1);
1285        float y = field.getYInterval()*(field.getNumRows()-1);
1286
1287        Vec3 base_1(Vec3(0,0,zMin));
1288        Vec3 base_2(Vec3(x,0,zMin));
1289        Vec3 base_3(Vec3(x,y,zMin));
1290        Vec3 base_4(Vec3(0,y,zMin));
1291
1292        Vec3 top_1(Vec3(0,0,zMax));
1293        Vec3 top_2(Vec3(x,0,zMax));
1294        Vec3 top_3(Vec3(x,y,zMax));
1295        Vec3 top_4(Vec3(0,y,zMax));
1296
1297        Matrix matrix = field.computeRotationMatrix();
1298        _bb.expandBy(field.getOrigin()+base_1*matrix);
1299        _bb.expandBy(field.getOrigin()+base_2*matrix);
1300        _bb.expandBy(field.getOrigin()+base_3*matrix);
1301        _bb.expandBy(field.getOrigin()+base_4*matrix);
1302
1303        _bb.expandBy(field.getOrigin()+top_1*matrix);
1304        _bb.expandBy(field.getOrigin()+top_2*matrix);
1305        _bb.expandBy(field.getOrigin()+top_3*matrix);
1306        _bb.expandBy(field.getOrigin()+top_4*matrix);
1307    }
1308
1309}
1310
1311void ComputeBoundShapeVisitor::apply(const CompositeShape& group)
1312{
1313    for(unsigned int i=0;i<group.getNumChildren();++i)
1314    {
1315        group.getChild(i)->accept(*this);
1316    }
1317}
1318
1319
1320
1321
1322///////////////////////////////////////////////////////////////////////////////
1323//
1324// Accept a primitive functor for each of the shapes.
1325//
1326
1327class PrimitiveShapeVisitor : public ConstShapeVisitor
1328{
1329    public:
1330   
1331        PrimitiveShapeVisitor(PrimitiveFunctor& functor,const TessellationHints* hints):
1332            _functor(functor),
1333            _hints(hints) {}
1334
1335        virtual void apply(const Sphere&);
1336        virtual void apply(const Box&);
1337        virtual void apply(const Cone&);
1338        virtual void apply(const Cylinder&);
1339        virtual void apply(const Capsule&);
1340        virtual void apply(const InfinitePlane&);
1341
1342        virtual void apply(const TriangleMesh&);
1343        virtual void apply(const ConvexHull&);
1344        virtual void apply(const HeightField&);
1345
1346        virtual void apply(const CompositeShape&);
1347
1348        PrimitiveFunctor& _functor;
1349        const TessellationHints*  _hints;
1350
1351    private:
1352
1353        PrimitiveShapeVisitor& operator = (const PrimitiveShapeVisitor&) { return *this; }
1354
1355        // helpers for apply( Cylinder | Sphere | Capsule )
1356        void createCylinderBody(unsigned int numSegments, float radius, float height, const osg::Matrix& matrix);
1357        void createHalfSphere(unsigned int numSegments, unsigned int numRows, float radius, int which, float zOffset, const osg::Matrix& matrix);
1358};
1359
1360
1361
1362void PrimitiveShapeVisitor::createCylinderBody(unsigned int numSegments, float radius, float height, const osg::Matrix& matrix)
1363{
1364    const float angleDelta = 2.0f*osg::PI/(float)numSegments;
1365   
1366    const float r = radius;
1367    const float h = height;
1368   
1369    float basez = -h*0.5f;
1370    float topz = h*0.5f;
1371   
1372    float angle = 0.0f;
1373   
1374    _functor.begin(GL_QUAD_STRIP);
1375
1376        for(unsigned int bodyi=0;
1377            bodyi<numSegments;
1378            ++bodyi,angle+=angleDelta)
1379        {
1380            float c = cosf(angle);
1381            float s = sinf(angle);
1382
1383            _functor.vertex(osg::Vec3(c*r,s*r,topz) * matrix);
1384            _functor.vertex(osg::Vec3(c*r,s*r,basez) * matrix);
1385        }
1386
1387        // do last point by hand to ensure no round off errors.
1388        _functor.vertex(osg::Vec3(r,0.0f,topz) * matrix);
1389        _functor.vertex(osg::Vec3(r,0.0f,basez) * matrix);
1390   
1391    _functor.end();
1392}
1393
1394
1395void PrimitiveShapeVisitor::createHalfSphere(unsigned int numSegments, unsigned int numRows, float radius, int which, float zOffset, const osg::Matrix& matrix)
1396{
1397    float lDelta = osg::PI/(float)numRows;
1398    float vDelta = 1.0f/(float)numRows;
1399
1400    // top half is 0, bottom is 1.
1401    bool top = (which==0);
1402
1403    float angleDelta = osg::PI*2.0f/(float)numSegments;
1404
1405    float lBase=-osg::PI*0.5f + (top?(lDelta*(numRows/2)):0.0f);
1406    float rBase=(top?(cosf(lBase)*radius):0.0f);
1407    float zBase=(top?(sinf(lBase)*radius):-radius);
1408    float vBase=(top?(vDelta*(numRows/2)):0.0f);
1409    float nzBase=(top?(sinf(lBase)):-1.0f);
1410    float nRatioBase=(top?(cosf(lBase)):0.0f);
1411
1412    unsigned int rowbegin = top?numRows/2:0;
1413    unsigned int rowend   = top?numRows:numRows/2;
1414
1415    for(unsigned int rowi=rowbegin; rowi<rowend; ++rowi)
1416    {
1417
1418        float lTop = lBase+lDelta;
1419        float rTop = cosf(lTop)*radius;
1420        float zTop = sinf(lTop)*radius;
1421        float vTop = vBase+vDelta;
1422        float nzTop= sinf(lTop);
1423        float nRatioTop= cosf(lTop);
1424
1425        _functor.begin(GL_QUAD_STRIP);
1426
1427            float angle = 0.0f;
1428
1429            for(unsigned int topi=0; topi<numSegments;
1430                ++topi,angle+=angleDelta)
1431            {
1432
1433                float c = cosf(angle);
1434                float s = sinf(angle);
1435
1436                _functor.vertex(osg::Vec3(c*rTop,s*rTop,zTop+zOffset) * matrix);
1437                _functor.vertex(osg::Vec3(c*rBase,s*rBase,zBase+zOffset) * matrix);
1438
1439            }
1440 
1441            // do last point by hand to ensure no round off errors.
1442            _functor.vertex(osg::Vec3(rTop,0.0f,zTop+zOffset) * matrix);
1443            _functor.vertex(osg::Vec3(rBase,0.0f,zBase+zOffset) * matrix);           
1444
1445        _functor.end();
1446       
1447       
1448        lBase=lTop;
1449        rBase=rTop;
1450        zBase=zTop;
1451        vBase=vTop;
1452        nzBase=nzTop;
1453        nRatioBase=nRatioTop;
1454
1455    }
1456       
1457}
1458
1459
1460
1461void PrimitiveShapeVisitor::apply(const Sphere& sphere)
1462{
1463
1464    float tx = sphere.getCenter().x();
1465    float ty = sphere.getCenter().y();
1466    float tz = sphere.getCenter().z();
1467
1468    unsigned int numSegments = 40;
1469    unsigned int numRows = 20;
1470    float ratio = (_hints ? _hints->getDetailRatio() : 1.0f);
1471    if (ratio > 0.0f && ratio != 1.0f) {
1472        numRows = (unsigned int) (numRows * ratio);
1473        if (numRows < MIN_NUM_ROWS)
1474            numRows = MIN_NUM_ROWS;
1475        numSegments = (unsigned int) (numSegments * ratio);
1476        if (numSegments < MIN_NUM_SEGMENTS)
1477            numSegments = MIN_NUM_SEGMENTS;
1478    }
1479
1480    float lDelta = osg::PI/(float)numRows;
1481    float vDelta = 1.0f/(float)numRows;
1482
1483    float angleDelta = osg::PI*2.0f/(float)numSegments;
1484
1485    float lBase=-osg::PI*0.5f;
1486    float rBase=0.0f;
1487    float zBase=-sphere.getRadius();
1488    float vBase=0.0f;
1489
1490    for(unsigned int rowi=0;
1491        rowi<numRows;
1492        ++rowi)
1493    {
1494
1495        float lTop = lBase+lDelta;
1496        float rTop = cosf(lTop)*sphere.getRadius();
1497        float zTop = sinf(lTop)*sphere.getRadius();
1498        float vTop = vBase+vDelta;
1499
1500        _functor.begin(GL_QUAD_STRIP);
1501
1502            float angle = 0.0f;
1503
1504            for(unsigned int topi=0;
1505                topi<numSegments;
1506                ++topi,angle+=angleDelta)
1507            {
1508
1509                float c = cosf(angle);
1510                float s = sinf(angle);
1511
1512                _functor.vertex(tx+c*rTop,ty+s*rTop,tz+zTop);
1513                _functor.vertex(tx+c*rBase,ty+s*rBase,tz+zBase);
1514
1515            }
1516
1517            // do last point by hand to ensure no round off errors.
1518            _functor.vertex(tx+rTop,ty,tz+zTop);
1519            _functor.vertex(tx+rBase,ty,tz+zBase);
1520
1521        _functor.end();
1522
1523        lBase=lTop;
1524        rBase=rTop;
1525        zBase=zTop;
1526        vBase=vTop;
1527
1528    }
1529}
1530
1531void PrimitiveShapeVisitor::apply(const Box& box)
1532{
1533    // evaluate hints
1534    bool createBody = (_hints ? _hints->getCreateBody() : true);
1535    bool createTop = (_hints ? _hints->getCreateTop() : true);
1536    bool createBottom = (_hints ? _hints->getCreateBottom() : true);
1537
1538    float x = box.getHalfLengths().x();
1539    float y = box.getHalfLengths().y();
1540    float z = box.getHalfLengths().z();
1541
1542    Vec3 base_1(-x,-y,-z);
1543    Vec3 base_2(x,-y,-z);
1544    Vec3 base_3(x,y,-z);
1545    Vec3 base_4(-x,y,-z);
1546
1547    Vec3 top_1(-x,-y,z);
1548    Vec3 top_2(x,-y,z);
1549    Vec3 top_3(x,y,z);
1550    Vec3 top_4(-x,y,z);
1551
1552    if (box.zeroRotation())
1553    {
1554        base_1 += box.getCenter();
1555        base_2 += box.getCenter();
1556        base_3 += box.getCenter();
1557        base_4 += box.getCenter();
1558
1559        top_1 += box.getCenter();
1560        top_2 += box.getCenter();
1561        top_3 += box.getCenter();
1562        top_4 += box.getCenter();
1563    }
1564    else
1565    {
1566        Matrix matrix = box.computeRotationMatrix();
1567        matrix.setTrans(box.getCenter());
1568       
1569        base_1 = base_1*matrix;
1570        base_2 = base_2*matrix;
1571        base_3 = base_3*matrix;
1572        base_4 = base_4*matrix;
1573
1574        top_1 = top_1*matrix;
1575        top_2 = top_2*matrix;
1576        top_3 = top_3*matrix;
1577        top_4 = top_4*matrix;
1578    }
1579
1580    _functor.begin(GL_QUADS);
1581    if (createBody)
1582    {
1583        _functor.vertex(top_1);
1584        _functor.vertex(base_1);
1585        _functor.vertex(base_2);
1586        _functor.vertex(top_2);
1587
1588        _functor.vertex(top_2);
1589        _functor.vertex(base_2);
1590        _functor.vertex(base_3);
1591        _functor.vertex(top_3);
1592
1593        _functor.vertex(top_3);
1594        _functor.vertex(base_3);
1595        _functor.vertex(base_4);
1596        _functor.vertex(top_4);
1597
1598        _functor.vertex(top_4);
1599        _functor.vertex(base_4);
1600        _functor.vertex(base_1);
1601        _functor.vertex(top_1);
1602    }
1603
1604    if (createTop)
1605    {
1606        _functor.vertex(top_4);
1607        _functor.vertex(top_1);
1608        _functor.vertex(top_2);
1609        _functor.vertex(top_3);
1610    }
1611
1612    if (createBottom)
1613    {
1614        _functor.vertex(base_4);
1615        _functor.vertex(base_3);
1616        _functor.vertex(base_2);
1617        _functor.vertex(base_1);
1618    }
1619
1620    _functor.end();
1621
1622}
1623
1624void PrimitiveShapeVisitor::apply(const Cone& cone)
1625{
1626    // evaluate hints
1627    bool createBody = (_hints ? _hints->getCreateBody() : true);
1628    bool createBottom = (_hints ? _hints->getCreateBottom() : true);
1629
1630    Matrix matrix = cone.computeRotationMatrix();
1631    matrix.setTrans(cone.getCenter());
1632
1633    unsigned int numSegments = 40;
1634    unsigned int numRows = 20;
1635    float ratio = (_hints ? _hints->getDetailRatio() : 1.0f);
1636    if (ratio > 0.0f && ratio != 1.0f) {
1637        numRows = (unsigned int) (numRows * ratio);
1638        if (numRows < MIN_NUM_ROWS)
1639            numRows = MIN_NUM_ROWS;
1640        numSegments = (unsigned int) (numSegments * ratio);
1641        if (numSegments < MIN_NUM_SEGMENTS)
1642            numSegments = MIN_NUM_SEGMENTS;
1643    }
1644
1645    float r = cone.getRadius();
1646    float h = cone.getHeight();
1647
1648    float normalz = r/(sqrtf(r*r+h*h));
1649    float normalRatio = 1.0f/(sqrtf(1.0f+normalz*normalz));
1650    normalz *= normalRatio;
1651
1652    float angleDelta = 2.0f*osg::PI/(float)numSegments;
1653    float hDelta = cone.getHeight()/(float)numRows;
1654    float rDelta = cone.getRadius()/(float)numRows;
1655
1656    float topz=cone.getHeight()+cone.getBaseOffset();
1657    float topr=0.0f;
1658    float basez=topz-hDelta;
1659    float baser=rDelta;
1660    float angle;
1661
1662    if (createBody)
1663    {
1664        for(unsigned int rowi=0;
1665            rowi<numRows;
1666            ++rowi,topz=basez, basez-=hDelta, topr=baser, baser+=rDelta)
1667        {
1668            // we can't use a fan for the cone top
1669            // since we need different normals at the top
1670            // for each face..
1671            _functor.begin(GL_QUAD_STRIP);
1672
1673                angle = 0.0f;
1674                for(unsigned int topi=0;
1675                    topi<numSegments;
1676                    ++topi,angle+=angleDelta)
1677                {
1678
1679                    float c = cosf(angle);
1680                    float s = sinf(angle);
1681
1682                    _functor.vertex(Vec3(c*topr,s*topr,topz)*matrix);
1683                    _functor.vertex(Vec3(c*baser,s*baser,basez)*matrix);
1684
1685                }
1686
1687                // do last point by hand to ensure no round off errors.
1688                _functor.vertex(Vec3(topr,0.0f,topz)*matrix);
1689                _functor.vertex(Vec3(baser,0.0f,basez)*matrix);
1690
1691            _functor.end();
1692
1693        }
1694    }
1695
1696    if (createBottom)
1697    {
1698        // we can't use a fan for the cone top
1699        // since we need different normals at the top
1700        // for each face..
1701        _functor.begin(GL_TRIANGLE_FAN);
1702
1703        angle = osg::PI*2.0f;
1704        basez = cone.getBaseOffset();
1705
1706        _functor.vertex(Vec3(0.0f,0.0f,basez)*matrix);
1707
1708        for(unsigned int bottomi=0;
1709            bottomi<numSegments;
1710            ++bottomi,angle-=angleDelta)
1711        {
1712
1713            float c = cosf(angle);
1714            float s = sinf(angle);
1715
1716            _functor.vertex(Vec3(c*r,s*r,basez)*matrix);
1717
1718        }
1719
1720        _functor.vertex(Vec3(r,0.0f,basez)*matrix);
1721
1722        _functor.end();
1723    }
1724}
1725
1726void PrimitiveShapeVisitor::apply(const Cylinder& cylinder)
1727{
1728    // evaluate hints
1729    bool createBody = (_hints ? _hints->getCreateBody() : true);
1730    bool createTop = (_hints ? _hints->getCreateTop() : true);
1731    bool createBottom = (_hints ? _hints->getCreateBottom() : true);
1732
1733    Matrix matrix = cylinder.computeRotationMatrix();
1734    matrix.setTrans(cylinder.getCenter());
1735
1736    unsigned int numSegments = 40;
1737    float ratio = (_hints ? _hints->getDetailRatio() : 1.0f);
1738    if (ratio > 0.0f && ratio != 1.0f) {
1739        numSegments = (unsigned int) (numSegments * ratio);
1740        if (numSegments < MIN_NUM_SEGMENTS)
1741            numSegments = MIN_NUM_SEGMENTS;
1742    }
1743
1744    float angleDelta = 2.0f*osg::PI/(float)numSegments;
1745
1746    float r = cylinder.getRadius();
1747    float h = cylinder.getHeight();
1748
1749    float basez = -h*0.5f;
1750    float topz = h*0.5f;
1751    float angle;
1752
1753    // cylinder body
1754    if (createBody)
1755        createCylinderBody(numSegments, cylinder.getRadius(), cylinder.getHeight(), matrix);
1756
1757    // cylinder top
1758    if (createTop)
1759    {
1760        _functor.begin(GL_TRIANGLE_FAN);
1761
1762            _functor.vertex(Vec3(0.0f,0.0f,topz)*matrix);
1763
1764            angle = 0.0f;
1765            for(unsigned int topi=0;
1766                topi<numSegments;
1767                ++topi,angle+=angleDelta)
1768            {
1769
1770                float c = cosf(angle);
1771                float s = sinf(angle);
1772
1773                _functor.vertex(Vec3(c*r,s*r,topz)*matrix);
1774
1775            }
1776
1777            _functor.vertex(Vec3(r,0.0f,topz)*matrix);
1778
1779        _functor.end();
1780    }
1781
1782    // cylinder bottom
1783    if (createBottom)
1784    {
1785        _functor.begin(GL_TRIANGLE_FAN);
1786
1787            _functor.vertex(Vec3(0.0f,0.0f,basez)*matrix);
1788
1789            angle = osg::PI*2.0f;
1790            for(unsigned int bottomi=0;
1791                bottomi<numSegments;
1792                ++bottomi,angle-=angleDelta)
1793            {
1794
1795                float c = cosf(angle);
1796                float s = sinf(angle);
1797
1798                _functor.vertex(Vec3(c*r,s*r,basez)*matrix);
1799
1800            }
1801
1802            _functor.vertex(Vec3(r,0.0f,basez)*matrix);
1803
1804        _functor.end();
1805    }
1806}
1807
1808void PrimitiveShapeVisitor::apply(const Capsule& capsule)
1809{
1810    // evaluate hints
1811    bool createBody = (_hints ? _hints->getCreateBody() : true);
1812    bool createTop = (_hints ? _hints->getCreateTop() : true);
1813    bool createBottom = (_hints ? _hints->getCreateBottom() : true);
1814
1815    Matrix matrix = capsule.computeRotationMatrix();
1816    matrix.setTrans(capsule.getCenter());
1817
1818    unsigned int numSegments = 40;
1819    unsigned int numRows = 20;
1820    float ratio = (_hints ? _hints->getDetailRatio() : 1.0f);
1821    if (ratio > 0.0f && ratio != 1.0f) {
1822        numRows = (unsigned int) (numRows * ratio);
1823        if (numRows < MIN_NUM_ROWS)
1824            numRows = MIN_NUM_ROWS;
1825        numSegments = (unsigned int) (numSegments * ratio);
1826        if (numSegments < MIN_NUM_SEGMENTS)
1827            numSegments = MIN_NUM_SEGMENTS;
1828    }
1829
1830    // capsule body
1831    if (createBody)
1832        createCylinderBody(numSegments, capsule.getRadius(), capsule.getHeight(), matrix);
1833
1834    // capsule top cap
1835    if (createTop)
1836        createHalfSphere(numSegments, numRows, capsule.getRadius(), 0, capsule.getHeight()/2.0f, matrix);
1837
1838    // capsule bottom cap
1839    if (createBottom)
1840        createHalfSphere(numSegments, numRows, capsule.getRadius(), 1, -capsule.getHeight()/2.0f, matrix);
1841
1842}
1843
1844void PrimitiveShapeVisitor::apply(const InfinitePlane&)
1845{
1846    OSG_NOTICE<<"Warning: PrimitiveShapeVisitor::apply(const InfinitePlane& plane) not yet implemented. "<<std::endl;
1847}
1848
1849void PrimitiveShapeVisitor::apply(const TriangleMesh& mesh)
1850{
1851    const Vec3Array* vertices = mesh.getVertices();
1852    const IndexArray* indices = mesh.getIndices();
1853   
1854     if (vertices && indices)
1855     {
1856        _functor.begin(GL_TRIANGLES);
1857
1858        for(unsigned int i=0;i<indices->getNumElements();i+=3)
1859        {
1860            _functor.vertex((*vertices)[indices->index(i)]);
1861            _functor.vertex((*vertices)[indices->index(i+1)]);
1862            _functor.vertex((*vertices)[indices->index(i+2)]);
1863        }
1864
1865        _functor.end();
1866     }
1867
1868
1869}
1870
1871void PrimitiveShapeVisitor::apply(const ConvexHull& hull)
1872{
1873    apply((const TriangleMesh&)hull);
1874}
1875
1876void PrimitiveShapeVisitor::apply(const HeightField& field)
1877{
1878    if (field.getNumColumns()==0 || field.getNumRows()==0) return;
1879   
1880    Matrix matrix = field.computeRotationMatrix();
1881    matrix.setTrans(field.getOrigin());
1882
1883    float dx = field.getXInterval();
1884    float dy = field.getYInterval();
1885
1886    for(unsigned int row=0;row<field.getNumRows()-1;++row)
1887    {
1888
1889        _functor.begin(GL_QUAD_STRIP);
1890
1891        for(unsigned int col=0;col<field.getNumColumns();++col)
1892        {
1893            Vec3 vertTop(dx*(float)col,dy*(float)(row+1),field.getHeight(col,row+1));
1894            Vec3 vertBase(dx*(float)col,dy*(float)row,field.getHeight(col,row));
1895
1896            _functor.vertex(vertTop*matrix);
1897            _functor.vertex(vertBase*matrix);
1898
1899        }
1900
1901        _functor.end();
1902    }
1903
1904}
1905
1906void PrimitiveShapeVisitor::apply(const CompositeShape& group)
1907{
1908    for(unsigned int i=0;i<group.getNumChildren();++i)
1909    {
1910        group.getChild(i)->accept(*this);
1911    }
1912}
1913
1914
1915///////////////////////////////////////////////////////////////////////////////
1916//
1917// ShapeDrawable itself..
1918//
1919
1920
1921ShapeDrawable::ShapeDrawable():
1922    _color(1.0f,1.0f,1.0f,1.0f)
1923{
1924    //setUseDisplayList(false);
1925}
1926
1927ShapeDrawable::ShapeDrawable(Shape* shape,TessellationHints* hints):
1928  _color(1.0f,1.0f,1.0f,1.0f),
1929  _tessellationHints(hints)
1930{
1931    setShape(shape);
1932    //setUseDisplayList(false);
1933}
1934
1935ShapeDrawable::ShapeDrawable(const ShapeDrawable& pg,const CopyOp& copyop):
1936    Drawable(pg,copyop),
1937    _color(pg._color),
1938    _tessellationHints(pg._tessellationHints)
1939{
1940    //setUseDisplayList(false);
1941}
1942
1943ShapeDrawable::~ShapeDrawable()
1944{
1945}
1946
1947void ShapeDrawable::setColor(const Vec4& color)
1948{
1949    if (_color!=color)
1950    {
1951        _color = color; dirtyDisplayList();
1952    }
1953}
1954
1955void ShapeDrawable::setTessellationHints(TessellationHints* hints)
1956{
1957    if (_tessellationHints!=hints)
1958    {
1959        _tessellationHints = hints;
1960        dirtyDisplayList();
1961    }
1962}
1963
1964void ShapeDrawable::drawImplementation(RenderInfo& renderInfo) const
1965{
1966    osg::State& state = *renderInfo.getState();
1967    GLBeginEndAdapter& gl = state.getGLBeginEndAdapter();
1968
1969    if (_shape.valid())
1970    {
1971        gl.Color4fv(_color.ptr());
1972   
1973        DrawShapeVisitor dsv(state,_tessellationHints.get());
1974       
1975        _shape->accept(dsv);
1976    }
1977}
1978
1979void ShapeDrawable::accept(ConstAttributeFunctor&) const
1980{
1981}
1982
1983void ShapeDrawable::accept(PrimitiveFunctor& pf) const
1984{
1985    if (_shape.valid())
1986    {
1987        PrimitiveShapeVisitor psv(pf,_tessellationHints.get());
1988        _shape->accept(psv);
1989    }
1990}
1991
1992
1993BoundingBox ShapeDrawable::computeBound() const
1994{
1995    BoundingBox bbox;
1996    if (_shape.valid())
1997    {
1998        ComputeBoundShapeVisitor cbsv(bbox);
1999        _shape->accept(cbsv);
2000    }
2001    return bbox;
2002}
Note: See TracBrowser for help on using the browser.