root/OpenSceneGraph/trunk/src/osgUtil/Tesselator.cpp @ 3209

Revision 3209, 26.0 kB (checked in by robert, 10 years ago)

From Geoff Michel, new osgtesselate example, and new features in osgUtil::Tesselator.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 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/GL>
14#include <osg/GLU>
15
16#include <osg/Notify>
17#include <osgUtil/Tesselator>
18
19using namespace osg;
20using namespace osgUtil;
21
22
23Tesselator::Tesselator() :
24    _wtype(TESS_WINDING_ODD),
25    _ttype(TESS_TYPE_POLYGONS),
26    _boundaryOnly(false), _numberVerts(0)
27{
28    _tobj = 0;
29    _errorCode = 0;
30    _index=0;
31}
32
33Tesselator::~Tesselator()
34{
35    reset();
36}
37
38void Tesselator::beginTesselation()
39{
40    reset();
41
42    if (!_tobj) _tobj = gluNewTess();
43   
44    gluTessCallback(_tobj, GLU_TESS_VERTEX_DATA, (GLvoid (CALLBACK*)()) vertexCallback);
45    gluTessCallback(_tobj, GLU_TESS_BEGIN_DATA,  (GLvoid (CALLBACK*)()) beginCallback);
46    gluTessCallback(_tobj, GLU_TESS_END_DATA,    (GLvoid (CALLBACK*)()) endCallback);
47    gluTessCallback(_tobj, GLU_TESS_COMBINE_DATA,(GLvoid (CALLBACK*)()) combineCallback);
48    gluTessCallback(_tobj, GLU_TESS_ERROR_DATA,  (GLvoid (CALLBACK*)()) errorCallback);
49
50    gluTessBeginPolygon(_tobj,this);
51}   
52   
53void Tesselator::beginContour()
54{
55    if (_tobj)
56    {
57        gluTessBeginContour(_tobj);
58    }
59}
60     
61void Tesselator::addVertex(osg::Vec3* vertex)
62{
63    if (_tobj)
64    {
65        Vec3d* data = new Vec3d;
66        _coordData.push_back(data);
67        (*data)._v[0]=(*vertex)[0];
68        (*data)._v[1]=(*vertex)[1];
69        (*data)._v[2]=(*vertex)[2];
70        gluTessVertex(_tobj,data->_v,vertex);
71    }
72}
73
74void Tesselator::endContour()
75{
76    if (_tobj)
77    {
78        gluTessEndContour(_tobj);
79    }
80}
81
82void Tesselator::endTesselation()
83{
84    if (_tobj)
85    {
86        gluTessEndPolygon(_tobj);
87        gluDeleteTess(_tobj);
88        _tobj = 0;
89       
90        if (_errorCode!=0)
91        {
92           const GLubyte *estring = gluErrorString((GLenum)_errorCode);
93           osg::notify(osg::WARN)<<"Tessellation Error: "<<estring<< std::endl;
94        }
95    }
96}
97
98void Tesselator::reset()
99{
100    if (_tobj)
101    {
102        gluDeleteTess(_tobj);
103        _tobj = 0;
104    }
105    for (Vec3dList::iterator i = _coordData.begin(); i != _coordData.end(); ++i) {
106      delete (*i);
107    }
108    _coordData.clear();
109    _newVertexList.clear();
110    _primList.clear();
111    _errorCode = 0;
112}
113
114class InsertNewVertices : public osg::ArrayVisitor
115{
116    public:
117   
118        float _f1,_f2,_f3,_f4;
119        unsigned int _i1,_i2,_i3,_i4;
120
121        InsertNewVertices(float f1,unsigned int i1,
122                          float f2,unsigned int i2,
123                          float f3,unsigned int i3,
124                          float f4,unsigned int i4):
125                            _f1(f1),_f2(f2),_f3(f3),_f4(f4),
126                            _i1(i1),_i2(i2),_i3(i3),_i4(i4){}
127
128        template <class ARRAY,class TYPE>
129        void apply_imp(ARRAY& array,TYPE initialValue)
130        {
131            TYPE val = initialValue;
132            if (_f1) val += static_cast<TYPE>(array[_i1] * _f1);
133            if (_f2) val += static_cast<TYPE>(array[_i2] * _f2);
134            if (_f3) val += static_cast<TYPE>(array[_i3] * _f3);
135            if (_f4) val += static_cast<TYPE>(array[_i4] * _f4);
136           
137            array.push_back(val);
138        }
139
140        virtual void apply(osg::ByteArray& ba) { apply_imp(ba,GLbyte(0)); }
141        virtual void apply(osg::ShortArray& ba) { apply_imp(ba,GLshort(0)); }
142        virtual void apply(osg::IntArray& ba) { apply_imp(ba,GLint(0)); }
143        virtual void apply(osg::UByteArray& ba) { apply_imp(ba,GLubyte(0)); }
144        virtual void apply(osg::UShortArray& ba) { apply_imp(ba,GLushort(0)); }
145        virtual void apply(osg::UIntArray& ba) { apply_imp(ba,GLuint(0)); }
146        virtual void apply(osg::UByte4Array& ba) { apply_imp(ba,UByte4()); }
147        virtual void apply(osg::FloatArray& ba) { apply_imp(ba,float(0)); }
148        virtual void apply(osg::Vec2Array& ba) { apply_imp(ba,Vec2()); }
149        virtual void apply(osg::Vec3Array& ba) { apply_imp(ba,Vec3()); }
150        virtual void apply(osg::Vec4Array& ba) { apply_imp(ba,Vec4()); }
151
152};
153
154void Tesselator::retesselatePolygons(osg::Geometry &geom)
155{
156    // turn the contour list into primitives, a little like tesselator does but more generally
157    osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray());
158   
159    if (!vertices || vertices->empty() || geom.getPrimitiveSetList().empty()) return;
160
161
162    // we currently don't handle geometry which use indices...
163    if (geom.getVertexIndices() ||
164        geom.getNormalIndices() ||
165        geom.getColorIndices() ||
166        geom.getSecondaryColorIndices() ||
167        geom.getFogCoordIndices()) return;
168       
169    // not even text coord indices don't handle geometry which use indices...
170    for(unsigned int unit=0;unit<geom.getNumTexCoordArrays();++unit)
171    {
172        if (geom.getTexCoordIndices(unit)) return;
173    }
174
175    if (_ttype==TESS_TYPE_POLYGONS || _ttype==TESS_TYPE_DRAWABLE) _numberVerts=0; // 09.04.04 GWM reset tesselator
176    // the reset is needed by the flt loader which reuses a tesselator for triangulating polygons.
177    // as such it might be reset by other loaders/developers in future.
178    _index=0; // reset the counter for indexed vertices
179    if (!_numberVerts) {
180        _numberVerts=geom.getVertexArray()->getNumElements();
181        // save the contours for complex (winding rule) tesselations
182        _Contours=geom.getPrimitiveSetList();
183    }
184
185    // now cut out vertex attributes added on any previous tesselation
186    reduceArray(geom.getVertexArray(), _numberVerts);
187    reduceArray(geom.getColorArray(), _numberVerts);
188    reduceArray(geom.getNormalArray(), _numberVerts);
189    reduceArray(geom.getFogCoordArray(), _numberVerts);
190    for(unsigned int unit1=0;unit1<geom.getNumTexCoordArrays();++unit1)
191    {
192        reduceArray(geom.getTexCoordArray(unit1), _numberVerts);
193    }
194
195    // remove the existing primitives.
196    unsigned int nprimsetoriginal= geom.getNumPrimitiveSets();
197    if (nprimsetoriginal) geom.removePrimitiveSet(0, nprimsetoriginal);
198
199    // the main difference from osgUtil::tesselator for Geometry sets of multiple contours is that the begin/end tesselation
200    // occurs around the whole set of contours.
201    if (_ttype==TESS_TYPE_GEOMETRY) {
202        beginTesselation();
203        gluTessProperty(_tobj, GLU_TESS_WINDING_RULE, _wtype);
204        gluTessProperty(_tobj, GLU_TESS_BOUNDARY_ONLY , _boundaryOnly);
205    }
206    // process all the contours into the tesselator
207    int noContours = _Contours.size();
208    for(int primNo=0;primNo<noContours;++primNo)
209    {
210        osg::ref_ptr<osg::PrimitiveSet> primitive = _Contours[primNo].get();
211        if (_ttype==TESS_TYPE_POLYGONS || _ttype==TESS_TYPE_DRAWABLE) {
212            if (primitive->getMode()==osg::PrimitiveSet::POLYGON ||_ttype==TESS_TYPE_DRAWABLE)  {
213                beginTesselation();
214                addContour(primitive.get(), vertices);
215                endTesselation();
216
217                collectTesselation(geom);
218            } else { // copy the contour primitive as it is not being tesselated
219                geom.addPrimitiveSet(primitive.get());
220            }
221        } else {
222            if (primitive->getMode()==osg::PrimitiveSet::POLYGON ||
223                primitive->getMode()==osg::PrimitiveSet::QUADS ||
224                primitive->getMode()==osg::PrimitiveSet::TRIANGLES ||
225                primitive->getMode()==osg::PrimitiveSet::LINE_LOOP ||
226                primitive->getMode()==osg::PrimitiveSet::QUAD_STRIP ||
227                primitive->getMode()==osg::PrimitiveSet::TRIANGLE_FAN ||
228                primitive->getMode()==osg::PrimitiveSet::TRIANGLE_STRIP)
229            {
230                addContour(primitive.get(), vertices);
231            } else { // copy the contour primitive as it is not being tesselated
232                // in this case points, lines or line_strip
233                geom.addPrimitiveSet(primitive.get());
234            }
235        }
236    }
237    if (_ttype==TESS_TYPE_GEOMETRY) {
238        endTesselation();
239   
240        collectTesselation(geom);   
241    }
242}
243
244void Tesselator::addContour(osg::PrimitiveSet* primitive, osg::Vec3Array* vertices)
245{
246    // adds a single primitive as a contour.
247    beginContour();
248    unsigned int nperprim=0; // number of vertices per primitive
249    if (primitive->getMode()==osg::PrimitiveSet::QUADS) nperprim=4;
250    if (primitive->getMode()==osg::PrimitiveSet::TRIANGLES) nperprim=3;
251    unsigned int idx=0;
252   
253    switch(primitive->getType())
254    {
255    case(osg::PrimitiveSet::DrawArraysPrimitiveType):
256        {
257            unsigned int i;
258            osg::DrawArrays* drawArray = static_cast<osg::DrawArrays*>(primitive);
259            unsigned int first = drawArray->getFirst();
260            unsigned int last = first+drawArray->getCount();
261
262            switch (primitive->getMode()) {
263            case osg::PrimitiveSet::QUADS:
264            case osg::PrimitiveSet::TRIANGLES:
265            case osg::PrimitiveSet::POLYGON:
266            case osg::PrimitiveSet::LINE_LOOP:
267            case osg::PrimitiveSet::TRIANGLE_FAN:
268                {
269                    for(i=first;i<last;++i, idx++)
270                    {
271                        addVertex(&((*vertices)[i]));
272                        if (nperprim>0 && i<last-1 && idx%nperprim==nperprim-1) {
273                            endContour();
274                            beginContour();
275                        }
276                    }
277                }
278                break;
279            case osg::PrimitiveSet::QUAD_STRIP:
280                { // always has an even number of vertices
281                    for( i=first;i<last;i+=2)
282                    { // 0,2,4...
283                        addVertex(&((*vertices)[i]));
284                    }
285                    for(i=last-1;i>=first;i-=2)
286                    { // ...5,3,1
287                        addVertex(&((*vertices)[i]));
288                    }
289                }
290                break;
291            case osg::PrimitiveSet::TRIANGLE_STRIP:
292                {
293                    for( i=first;i<last;i+=2)
294                    {// 0,2,4,...
295                        addVertex(&((*vertices)[i]));
296                    }
297                    for(i=((last-first)%2)?(last-2):(last-1) ;i>first&& i<last;i-=2)
298                    {
299                        addVertex(&((*vertices)[i]));
300                    }
301                }
302                break;
303            default: // lines, points, line_strip
304                {
305                    for(i=first;i<last;++i, idx++)
306                    {
307                        addVertex(&((*vertices)[i]));
308                        if (nperprim>0 && i<last-1 && idx%nperprim==nperprim-1) {
309                            endContour();
310                            beginContour();
311                        }
312                    }
313                }
314                break;
315            }
316            break;
317        }
318    case(osg::PrimitiveSet::DrawElementsUBytePrimitiveType):
319        {
320            osg::DrawElementsUByte* drawElements = static_cast<osg::DrawElementsUByte*>(primitive);
321            for(osg::DrawElementsUByte::iterator indexItr=drawElements->begin();
322            indexItr!=drawElements->end();
323            ++indexItr, idx++)
324            {
325                addVertex(&((*vertices)[*indexItr]));
326                if (nperprim>0 && indexItr!=drawElements->end() && idx%nperprim==nperprim-1) {
327                    endContour();
328                    beginContour();
329                }
330            }
331            break;
332        }
333    case(osg::PrimitiveSet::DrawElementsUShortPrimitiveType):
334        {
335            osg::DrawElementsUShort* drawElements = static_cast<osg::DrawElementsUShort*>(primitive);
336            for(osg::DrawElementsUShort::iterator indexItr=drawElements->begin();
337            indexItr!=drawElements->end();
338            ++indexItr, idx++)
339            {
340                addVertex(&((*vertices)[*indexItr]));
341                if (nperprim>0 && indexItr!=drawElements->end() && idx%nperprim==nperprim-1) {
342                    endContour();
343                    beginContour();
344                }
345            }
346            break;
347        }
348    case(osg::PrimitiveSet::DrawElementsUIntPrimitiveType):
349        {
350            osg::DrawElementsUInt* drawElements = static_cast<osg::DrawElementsUInt*>(primitive);
351            for(osg::DrawElementsUInt::iterator indexItr=drawElements->begin();
352            indexItr!=drawElements->end();
353            ++indexItr, idx++)
354            {
355                addVertex(&((*vertices)[*indexItr]));
356                if (nperprim>0 && indexItr!=drawElements->end() && idx%nperprim==nperprim-1) {
357                    endContour();
358                    beginContour();
359                }
360            }
361            break;
362        }
363    default:
364        break;
365    }
366   
367    endContour();
368}
369
370void Tesselator::handleNewVertices(osg::Geometry& geom,VertexPtrToIndexMap &vertexPtrToIndexMap)
371{
372    if (!_newVertexList.empty())
373    {
374       
375        osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray());
376        osg::Vec3Array* normals = NULL;
377        if (geom.getNormalBinding()==osg::Geometry::BIND_PER_VERTEX)
378        {
379            normals = geom.getNormalArray();
380        }
381       
382        typedef std::vector<osg::Array*> ArrayList;
383        ArrayList arrays;
384       
385        if (geom.getColorBinding()==osg::Geometry::BIND_PER_VERTEX)
386        {
387            arrays.push_back(geom.getColorArray());
388        }
389       
390        if (geom.getSecondaryColorBinding()==osg::Geometry::BIND_PER_VERTEX)
391        {
392            arrays.push_back(geom.getSecondaryColorArray());
393        }
394       
395        if (geom.getFogCoordBinding()==osg::Geometry::BIND_PER_VERTEX)
396        {
397            arrays.push_back(geom.getFogCoordArray());
398        }
399       
400        osg::Geometry::ArrayList& tcal = geom.getTexCoordArrayList();
401        for(osg::Geometry::ArrayList::iterator tcalItr=tcal.begin();
402        tcalItr!=tcal.end();
403        ++tcalItr)
404        {
405            if (tcalItr->array.valid())
406            {
407                arrays.push_back(tcalItr->array.get());
408            }
409        }
410       
411        // now add any new vertices that are required.
412        for(NewVertexList::iterator itr=_newVertexList.begin();
413        itr!=_newVertexList.end();
414        ++itr)
415        {
416            NewVertex& newVertex = (*itr);
417            osg::Vec3* vertex = newVertex._vpos;
418           
419            // assign vertex.
420            vertexPtrToIndexMap[vertex]=vertices->size();
421            vertices->push_back(*vertex);
422           
423            // assign normals
424            if (normals)
425            {
426                osg::Vec3 norm(0.0f,0.0f,0.0f);
427                if (newVertex._v1) norm += (*normals)[vertexPtrToIndexMap[newVertex._v1]] * newVertex._f1;
428                if (newVertex._v2) norm += (*normals)[vertexPtrToIndexMap[newVertex._v2]] * newVertex._f2;
429                if (newVertex._v3) norm += (*normals)[vertexPtrToIndexMap[newVertex._v3]] * newVertex._f3;
430                if (newVertex._v4) norm += (*normals)[vertexPtrToIndexMap[newVertex._v4]] * newVertex._f4;
431                norm.normalize();
432                normals->push_back(norm);
433            }
434           
435            if (!arrays.empty())
436            {
437                InsertNewVertices inv(newVertex._f1,vertexPtrToIndexMap[newVertex._v1],
438                    newVertex._f2,vertexPtrToIndexMap[newVertex._v2],
439                    newVertex._f3,vertexPtrToIndexMap[newVertex._v3],
440                    newVertex._f4,vertexPtrToIndexMap[newVertex._v4]);
441               
442                // assign the rest of the attributes.
443                for(ArrayList::iterator aItr=arrays.begin();
444                aItr!=arrays.end();
445                ++aItr)
446                {
447                    (*aItr)->accept(inv);
448                }
449            }
450        }
451       
452    }
453   
454}
455
456void Tesselator::begin(GLenum mode)
457{
458    _primList.push_back(new Prim(mode));
459}
460
461void Tesselator::vertex(osg::Vec3* vertex)
462{
463    if (!_primList.empty())
464    {
465        Prim* prim = _primList.back().get();
466        prim->_vertices.push_back(vertex);
467
468    }
469}
470
471void Tesselator::combine(osg::Vec3* vertex,void* vertex_data[4],GLfloat weight[4])
472{
473    _newVertexList.push_back(NewVertex(vertex,
474                                    weight[0],(Vec3*)vertex_data[0],
475                                     weight[1],(Vec3*)vertex_data[1],
476                                     weight[2],(Vec3*)vertex_data[2],
477                                     weight[3],(Vec3*)vertex_data[3]));
478}
479
480void Tesselator::end()
481{
482    // no need to do anything right now...
483}
484
485void Tesselator::error(GLenum errorCode)
486{
487    _errorCode = errorCode;
488}
489
490void CALLBACK Tesselator::beginCallback(GLenum which, void* userData)
491{
492    ((Tesselator*)userData)->begin(which);
493}
494
495void CALLBACK Tesselator::endCallback(void* userData)
496{
497    ((Tesselator*)userData)->end();
498}
499
500void CALLBACK Tesselator::vertexCallback(GLvoid *data, void* userData)
501{
502    ((Tesselator*)userData)->vertex((Vec3*)data);
503}
504
505void CALLBACK Tesselator::combineCallback(GLdouble coords[3], void* vertex_data[4],
506                              GLfloat weight[4], void** outData,
507                              void* userData)
508{
509    Vec3* newData = new osg::Vec3(coords[0],coords[1],coords[2]);
510    *outData = newData;
511    ((Tesselator*)userData)->combine(newData,vertex_data,weight);
512}
513
514void CALLBACK Tesselator::errorCallback(GLenum errorCode, void* userData)
515{
516    ((Tesselator*)userData)->error(errorCode);
517}
518
519void Tesselator::reduceArray(osg::Array * cold, const unsigned int nnu)
520{ // shrinks size of array to N
521    if (cold && cold->getNumElements()>nnu) {
522        osg::Vec2Array* v2arr = NULL;
523        osg::Vec3Array* v3arr = NULL;
524        osg::Vec4Array* v4arr = NULL;
525        switch (cold->getType()) {
526        case osg::Array::Vec2ArrayType: {
527            v2arr = dynamic_cast<osg::Vec2Array*>(cold);
528            osg::Vec2Array::iterator itr=v2arr->begin()+nnu;
529            (*v2arr).erase(itr, v2arr->end());
530                                        }
531            break;
532        case osg::Array::Vec3ArrayType: {
533            v3arr = dynamic_cast<osg::Vec3Array*>(cold);
534            osg::Vec3Array::iterator itr=v3arr->begin()+nnu;
535            (*v3arr).erase(itr, v3arr->end());
536                                        }
537            break;
538        case osg::Array::Vec4ArrayType: {
539            v4arr = dynamic_cast<osg::Vec4Array*>(cold);
540            osg::Vec4Array::iterator itr=v4arr->begin()+nnu;
541            (*v4arr).erase(itr, v4arr->end());
542                                        }
543            break;
544        default: // should also handle:ArrayType' ByteArrayType' ShortArrayType' IntArrayType'
545        // `UShortArrayType'  `UIntArrayType'  `UByte4ArrayType'  `FloatArrayType'
546            break;
547        }
548    }
549}
550
551unsigned int _computeNumberOfPrimitives(const osg::Geometry& geom)
552{
553
554    unsigned int totalNumberOfPrimitives = 0;
555   
556    for(Geometry::PrimitiveSetList::const_iterator itr=geom.getPrimitiveSetList().begin();
557        itr!=geom.getPrimitiveSetList().end();
558        ++itr)
559    {
560        const PrimitiveSet* primitiveset = itr->get();
561        GLenum mode=primitiveset->getMode();
562
563        unsigned int primLength;
564        switch(mode)
565        {
566            case(GL_POINTS):    primLength=1; break;
567            case(GL_LINES):     primLength=2; break;
568            case(GL_TRIANGLES): primLength=3; break;
569            case(GL_QUADS):     primLength=4; break;
570            default:            primLength=0; break; // compute later when =0.
571        }
572
573        // draw primtives by the more flexible "slow" path,
574        // sending OpenGL glBegin/glVertex.../glEnd().
575        switch(primitiveset->getType())
576        {
577            case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
578            {
579
580                const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
581                for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
582                    primItr!=drawArrayLengths->end();
583                    ++primItr)
584                {
585                    if (primLength==0) totalNumberOfPrimitives += 1;
586                    else totalNumberOfPrimitives += *primItr/primLength; // Dec 2003 - increment not set
587                }
588                break;
589            }
590            default:
591            {
592                if (primLength==0) totalNumberOfPrimitives += 1;
593                else totalNumberOfPrimitives += primitiveset->getNumIndices()/primLength;
594            }
595        }
596    }
597
598    return totalNumberOfPrimitives;
599}
600//
601void Tesselator::collectTesselation(osg::Geometry &geom)
602{
603    osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray());
604    VertexPtrToIndexMap vertexPtrToIndexMap;
605   
606    // populate the VertexPtrToIndexMap.
607    for(unsigned int vi=0;vi<vertices->size();++vi)
608    {
609        vertexPtrToIndexMap[&((*vertices)[vi])] = vi;
610    }
611   
612    handleNewVertices(geom, vertexPtrToIndexMap);
613   
614    // we don't properly handle per primitive and per primitive_set bindings yet
615    // will need to address this soon. Robert Oct 2002.
616    {
617        osg::Vec3Array* normals = NULL; // GWM Sep 2002 - add normals for extra facets
618        int iprim=0;
619        if (geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE ||
620            geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE_SET)
621        {
622            normals = geom.getNormalArray(); // GWM Sep 2002
623        }
624        // GWM Dec 2003 - needed to add colours for extra facets
625        osg::Vec4Array* cols4 = NULL; // GWM Dec 2003 colours are vec4
626        osg::Vec3Array* cols3 = NULL; // GWM Dec 2003 colours are vec3
627        if (geom.getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE ||
628              geom.getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE_SET)
629        {
630              Array* colours = geom.getColorArray(); // GWM Dec 2003 - need to duplicate face colours
631              switch (colours->getType()) {
632              case osg::Array::Vec4ArrayType:
633                  cols4=dynamic_cast<osg::Vec4Array *> (colours);
634                  break;
635              case osg::Array::Vec3ArrayType:
636                  cols3=dynamic_cast<osg::Vec3Array *> (colours);
637                  break;
638              default:
639                  break;
640              }
641             
642        }
643        // GWM Dec 2003 - these holders need to go outside the loop to
644        // retain the flat shaded colour &/or normal for each tesselated polygon
645        osg::Vec3 norm(0.0f,0.0f,0.0f);
646        osg::Vec4 primCol4(0.0f,0.0f,0.0f,1.0f);
647        osg::Vec3 primCol3(0.0f,0.0f,0.0f);
648
649        for(PrimList::iterator primItr=_primList.begin();
650        primItr!=_primList.end();
651        ++primItr, ++_index)
652        {
653              Prim* prim = primItr->get();
654             
655              osg::DrawElementsUShort* elements = new osg::DrawElementsUShort(prim->_mode);
656              for(Prim::VecList::iterator vitr=prim->_vertices.begin();
657              vitr!=prim->_vertices.end();
658              ++vitr)
659              {
660                  elements->push_back(vertexPtrToIndexMap[*vitr]);
661              }
662             
663              // add to the drawn primitive list.
664              geom.addPrimitiveSet(elements);
665              if (primItr==_primList.begin())
666              {   // first primitive so collect primitive normal & colour.
667                  if (normals) {
668                      norm=(*normals)[iprim]; // GWM Sep 2002 the flat shaded normal
669                  }
670                  if (cols4) {
671                      primCol4=(*cols4)[iprim]; // GWM Dec 2003 the flat shaded rgba colour
672                    if (_index>=cols4->size()) {
673                        cols4->push_back(primCol4); // GWM Dec 2003 add flat shaded colour for new facet
674                    }
675                  }
676                  if (cols3) {
677                      primCol3=(*cols3)[iprim]; // GWM Dec 2003 flat shaded rgb colour
678                    if (_index>=cols4->size()) {
679                        cols3->push_back(primCol3); // GWM Dec 2003 add flat shaded colour for new facet
680                    }
681                  }
682              }
683              else
684              { // later primitives use same colour
685                  if (normals) normals->push_back(norm); // GWM Sep 2002 add flat shaded normal for new facet
686                  if (cols4 && _index>=cols4->size()) {
687                    cols4->push_back(primCol4); // GWM Dec 2003 add flat shaded colour for new facet
688                  }
689                  if (cols3 && _index>=cols3->size()) {
690                    if (cols3) cols3->push_back(primCol3); // GWM Dec 2003 add flat shaded colour for new facet
691                  }
692                  if (prim->_mode==GL_TRIANGLES) {
693                      int ntris=elements->getNumIndices()/3;
694                      if (geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE_SET ||
695                          geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE) { // need one per triangle? Not one per set.
696                          for (int ii=1; ii<ntris; ii++) {
697                              if (normals) normals->push_back(norm); // GWM Sep 2002 add flat shaded normal for new facet
698                          }
699                      }
700                      if (geom.getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE_SET ||
701                          geom.getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE) { // need one per triangle? Not one per set.
702                          for (int ii=1; ii<ntris; ii++) {
703                              if (cols3 && _index>=cols3->size()) {
704                                  if (cols3) cols3->push_back(primCol3);
705                              }
706                              if (cols4 && _index>=cols4->size()) {
707                                  if (cols4) cols4->push_back(primCol4);
708                              }
709                              _index++;
710                          }
711                      }
712                  }
713                  //        osg::notify(osg::WARN)<<"Add: "<< iprim << std::endl;
714              }
715              iprim++; // GWM Sep 2002 count which normal we should use
716        }
717    }
718}
Note: See TracBrowser for help on using the browser.