root/OpenSceneGraph/trunk/src/osgUtil/Tessellator.cpp @ 13041

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