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

Revision 3326, 27.3 kB (checked in by robert, 10 years ago)

Added handling of DrawArrayLengths? PrimitiveSet?.

  • 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        {
213            if (primitive->getMode()==osg::PrimitiveSet::POLYGON || _ttype==TESS_TYPE_DRAWABLE)
214            {
215
216                if (primitive->getType()==osg::PrimitiveSet::DrawArrayLengthsPrimitiveType)
217                {
218                    osg::DrawArrayLengths* drawArrayLengths = static_cast<osg::DrawArrayLengths*>(primitive.get());
219                    unsigned int first = drawArrayLengths->getFirst();
220                    for(osg::DrawArrayLengths::iterator itr=drawArrayLengths->begin();
221                        itr!=drawArrayLengths->end();
222                        ++itr)
223                    {
224                        beginTesselation();
225                            unsigned int last = first + *itr;
226                            addContour(primitive->getMode(),first,last,vertices);
227                            first = last;
228                        endTesselation();
229                        collectTesselation(geom);
230                    }
231                }
232                else
233                {
234                    beginTesselation();
235                        addContour(primitive.get(), vertices);
236                    endTesselation();
237                    collectTesselation(geom);
238                }
239
240            }
241            else
242            { // copy the contour primitive as it is not being tesselated
243                geom.addPrimitiveSet(primitive.get());
244            }
245        } else {
246            if (primitive->getMode()==osg::PrimitiveSet::POLYGON ||
247                primitive->getMode()==osg::PrimitiveSet::QUADS ||
248                primitive->getMode()==osg::PrimitiveSet::TRIANGLES ||
249                primitive->getMode()==osg::PrimitiveSet::LINE_LOOP ||
250                primitive->getMode()==osg::PrimitiveSet::QUAD_STRIP ||
251                primitive->getMode()==osg::PrimitiveSet::TRIANGLE_FAN ||
252                primitive->getMode()==osg::PrimitiveSet::TRIANGLE_STRIP)
253            {
254                addContour(primitive.get(), vertices);
255            } else { // copy the contour primitive as it is not being tesselated
256                // in this case points, lines or line_strip
257                geom.addPrimitiveSet(primitive.get());
258            }
259        }
260    }
261    if (_ttype==TESS_TYPE_GEOMETRY) {
262        endTesselation();
263   
264        collectTesselation(geom);   
265    }
266}
267
268void Tesselator::addContour(GLenum mode, unsigned int first, unsigned int last, osg::Vec3Array* vertices)
269{
270    beginContour();
271
272    unsigned int idx=0;
273    unsigned int nperprim=0; // number of vertices per primitive
274    if (mode==osg::PrimitiveSet::QUADS) nperprim=4;
275    else if (mode==osg::PrimitiveSet::TRIANGLES) nperprim=3;
276
277    unsigned int i;
278    switch (mode)
279    {
280    case osg::PrimitiveSet::QUADS:
281    case osg::PrimitiveSet::TRIANGLES:
282    case osg::PrimitiveSet::POLYGON:
283    case osg::PrimitiveSet::LINE_LOOP:
284    case osg::PrimitiveSet::TRIANGLE_FAN:
285        {
286            for(i=first;i<last;++i, idx++)
287            {
288                addVertex(&((*vertices)[i]));
289                if (nperprim>0 && i<last-1 && idx%nperprim==nperprim-1) {
290                    endContour();
291                    beginContour();
292                }
293            }
294        }
295        break;
296    case osg::PrimitiveSet::QUAD_STRIP:
297        { // always has an even number of vertices
298            for(i=first;i<last;i+=2)
299            { // 0,2,4...
300                addVertex(&((*vertices)[i]));
301            }
302            for(i=last-1;i>=first;i-=2)
303            { // ...5,3,1
304                addVertex(&((*vertices)[i]));
305            }
306        }
307        break;
308    case osg::PrimitiveSet::TRIANGLE_STRIP:
309        {
310            for( i=first;i<last;i+=2)
311            {// 0,2,4,...
312                addVertex(&((*vertices)[i]));
313            }
314            for(i=((last-first)%2)?(last-2):(last-1) ;i>first&& i<last;i-=2)
315            {
316                addVertex(&((*vertices)[i]));
317            }
318        }
319        break;
320    default: // lines, points, line_strip
321        {
322            for(i=first;i<last;++i, idx++)
323            {
324                addVertex(&((*vertices)[i]));
325                if (nperprim>0 && i<last-1 && idx%nperprim==nperprim-1) {
326                    endContour();
327                    beginContour();
328                }
329            }
330        }
331        break;
332    }
333
334    endContour();
335}
336
337void Tesselator::addContour(osg::PrimitiveSet* primitive, osg::Vec3Array* vertices)
338{
339    // adds a single primitive as a contour.
340    unsigned int nperprim=0; // number of vertices per primitive
341    if (primitive->getMode()==osg::PrimitiveSet::QUADS) nperprim=4;
342    if (primitive->getMode()==osg::PrimitiveSet::TRIANGLES) nperprim=3;
343    unsigned int idx=0;
344   
345    switch(primitive->getType())
346    {
347    case(osg::PrimitiveSet::DrawArraysPrimitiveType):
348        {
349            osg::DrawArrays* drawArray = static_cast<osg::DrawArrays*>(primitive);
350            unsigned int first = drawArray->getFirst();
351            unsigned int last = first+drawArray->getCount();
352            addContour(primitive->getMode(),first,last,vertices);
353            break;
354         }
355    case(osg::PrimitiveSet::DrawElementsUBytePrimitiveType):
356        {
357            beginContour();
358            osg::DrawElementsUByte* drawElements = static_cast<osg::DrawElementsUByte*>(primitive);
359            for(osg::DrawElementsUByte::iterator indexItr=drawElements->begin();
360                indexItr!=drawElements->end();
361                ++indexItr, idx++)
362            {
363                addVertex(&((*vertices)[*indexItr]));
364                if (nperprim>0 && indexItr!=drawElements->end() && idx%nperprim==nperprim-1) {
365                    endContour();
366                    beginContour();
367                }
368            }
369            endContour();
370            break;
371        }
372    case(osg::PrimitiveSet::DrawElementsUShortPrimitiveType):
373        {
374            beginContour();
375            osg::DrawElementsUShort* drawElements = static_cast<osg::DrawElementsUShort*>(primitive);
376            for(osg::DrawElementsUShort::iterator indexItr=drawElements->begin();
377                indexItr!=drawElements->end();
378                ++indexItr, idx++)
379            {
380                addVertex(&((*vertices)[*indexItr]));
381                if (nperprim>0 && indexItr!=drawElements->end() && idx%nperprim==nperprim-1) {
382                    endContour();
383                    beginContour();
384                }
385            }
386            endContour();
387            break;
388        }
389    case(osg::PrimitiveSet::DrawElementsUIntPrimitiveType):
390        {
391            beginContour();
392            osg::DrawElementsUInt* drawElements = static_cast<osg::DrawElementsUInt*>(primitive);
393            for(osg::DrawElementsUInt::iterator indexItr=drawElements->begin();
394                indexItr!=drawElements->end();
395                ++indexItr, idx++)
396            {
397                addVertex(&((*vertices)[*indexItr]));
398                if (nperprim>0 && indexItr!=drawElements->end() && idx%nperprim==nperprim-1) {
399                    endContour();
400                    beginContour();
401                }
402            }
403            endContour();
404            break;
405        }
406    default:
407        osg::notify(osg::NOTICE)<<"Tesselator::addContour(primitive, vertices) : Primitive type "<<primitive->getType()<<" not handled"<<std::endl;
408        break;
409    }
410   
411}
412
413void Tesselator::handleNewVertices(osg::Geometry& geom,VertexPtrToIndexMap &vertexPtrToIndexMap)
414{
415    if (!_newVertexList.empty())
416    {
417       
418        osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray());
419        osg::Vec3Array* normals = NULL;
420        if (geom.getNormalBinding()==osg::Geometry::BIND_PER_VERTEX)
421        {
422            normals = geom.getNormalArray();
423        }
424       
425        typedef std::vector<osg::Array*> ArrayList;
426        ArrayList arrays;
427       
428        if (geom.getColorBinding()==osg::Geometry::BIND_PER_VERTEX)
429        {
430            arrays.push_back(geom.getColorArray());
431        }
432       
433        if (geom.getSecondaryColorBinding()==osg::Geometry::BIND_PER_VERTEX)
434        {
435            arrays.push_back(geom.getSecondaryColorArray());
436        }
437       
438        if (geom.getFogCoordBinding()==osg::Geometry::BIND_PER_VERTEX)
439        {
440            arrays.push_back(geom.getFogCoordArray());
441        }
442       
443        osg::Geometry::ArrayList& tcal = geom.getTexCoordArrayList();
444        for(osg::Geometry::ArrayList::iterator tcalItr=tcal.begin();
445            tcalItr!=tcal.end();
446            ++tcalItr)
447        {
448            if (tcalItr->array.valid())
449            {
450                arrays.push_back(tcalItr->array.get());
451            }
452        }
453       
454        // now add any new vertices that are required.
455        for(NewVertexList::iterator itr=_newVertexList.begin();
456            itr!=_newVertexList.end();
457            ++itr)
458        {
459            NewVertex& newVertex = (*itr);
460            osg::Vec3* vertex = newVertex._vpos;
461           
462            // assign vertex.
463            vertexPtrToIndexMap[vertex]=vertices->size();
464            vertices->push_back(*vertex);
465           
466            // assign normals
467            if (normals)
468            {
469                osg::Vec3 norm(0.0f,0.0f,0.0f);
470                if (newVertex._v1) norm += (*normals)[vertexPtrToIndexMap[newVertex._v1]] * newVertex._f1;
471                if (newVertex._v2) norm += (*normals)[vertexPtrToIndexMap[newVertex._v2]] * newVertex._f2;
472                if (newVertex._v3) norm += (*normals)[vertexPtrToIndexMap[newVertex._v3]] * newVertex._f3;
473                if (newVertex._v4) norm += (*normals)[vertexPtrToIndexMap[newVertex._v4]] * newVertex._f4;
474                norm.normalize();
475                normals->push_back(norm);
476            }
477           
478            if (!arrays.empty())
479            {
480                InsertNewVertices inv(newVertex._f1,vertexPtrToIndexMap[newVertex._v1],
481                    newVertex._f2,vertexPtrToIndexMap[newVertex._v2],
482                    newVertex._f3,vertexPtrToIndexMap[newVertex._v3],
483                    newVertex._f4,vertexPtrToIndexMap[newVertex._v4]);
484               
485                // assign the rest of the attributes.
486                for(ArrayList::iterator aItr=arrays.begin();
487                aItr!=arrays.end();
488                ++aItr)
489                {
490                    (*aItr)->accept(inv);
491                }
492            }
493        }
494       
495    }
496   
497}
498
499void Tesselator::begin(GLenum mode)
500{
501    _primList.push_back(new Prim(mode));
502}
503
504void Tesselator::vertex(osg::Vec3* vertex)
505{
506    if (!_primList.empty())
507    {
508        Prim* prim = _primList.back().get();
509        prim->_vertices.push_back(vertex);
510
511    }
512}
513
514void Tesselator::combine(osg::Vec3* vertex,void* vertex_data[4],GLfloat weight[4])
515{
516    _newVertexList.push_back(NewVertex(vertex,
517                                    weight[0],(Vec3*)vertex_data[0],
518                                     weight[1],(Vec3*)vertex_data[1],
519                                     weight[2],(Vec3*)vertex_data[2],
520                                     weight[3],(Vec3*)vertex_data[3]));
521}
522
523void Tesselator::end()
524{
525    // no need to do anything right now...
526}
527
528void Tesselator::error(GLenum errorCode)
529{
530    _errorCode = errorCode;
531}
532
533void CALLBACK Tesselator::beginCallback(GLenum which, void* userData)
534{
535    ((Tesselator*)userData)->begin(which);
536}
537
538void CALLBACK Tesselator::endCallback(void* userData)
539{
540    ((Tesselator*)userData)->end();
541}
542
543void CALLBACK Tesselator::vertexCallback(GLvoid *data, void* userData)
544{
545    ((Tesselator*)userData)->vertex((Vec3*)data);
546}
547
548void CALLBACK Tesselator::combineCallback(GLdouble coords[3], void* vertex_data[4],
549                              GLfloat weight[4], void** outData,
550                              void* userData)
551{
552    Vec3* newData = new osg::Vec3(coords[0],coords[1],coords[2]);
553    *outData = newData;
554    ((Tesselator*)userData)->combine(newData,vertex_data,weight);
555}
556
557void CALLBACK Tesselator::errorCallback(GLenum errorCode, void* userData)
558{
559    ((Tesselator*)userData)->error(errorCode);
560}
561
562void Tesselator::reduceArray(osg::Array * cold, const unsigned int nnu)
563{ // shrinks size of array to N
564    if (cold && cold->getNumElements()>nnu) {
565        osg::Vec2Array* v2arr = NULL;
566        osg::Vec3Array* v3arr = NULL;
567        osg::Vec4Array* v4arr = NULL;
568        switch (cold->getType()) {
569        case osg::Array::Vec2ArrayType: {
570            v2arr = dynamic_cast<osg::Vec2Array*>(cold);
571            osg::Vec2Array::iterator itr=v2arr->begin()+nnu;
572            (*v2arr).erase(itr, v2arr->end());
573                                        }
574            break;
575        case osg::Array::Vec3ArrayType: {
576            v3arr = dynamic_cast<osg::Vec3Array*>(cold);
577            osg::Vec3Array::iterator itr=v3arr->begin()+nnu;
578            (*v3arr).erase(itr, v3arr->end());
579                                        }
580            break;
581        case osg::Array::Vec4ArrayType: {
582            v4arr = dynamic_cast<osg::Vec4Array*>(cold);
583            osg::Vec4Array::iterator itr=v4arr->begin()+nnu;
584            (*v4arr).erase(itr, v4arr->end());
585                                        }
586            break;
587        default: // should also handle:ArrayType' ByteArrayType' ShortArrayType' IntArrayType'
588        // `UShortArrayType'  `UIntArrayType'  `UByte4ArrayType'  `FloatArrayType'
589            break;
590        }
591    }
592}
593
594unsigned int _computeNumberOfPrimitives(const osg::Geometry& geom)
595{
596
597    unsigned int totalNumberOfPrimitives = 0;
598   
599    for(Geometry::PrimitiveSetList::const_iterator itr=geom.getPrimitiveSetList().begin();
600        itr!=geom.getPrimitiveSetList().end();
601        ++itr)
602    {
603        const PrimitiveSet* primitiveset = itr->get();
604        GLenum mode=primitiveset->getMode();
605
606        unsigned int primLength;
607        switch(mode)
608        {
609            case(GL_POINTS):    primLength=1; break;
610            case(GL_LINES):     primLength=2; break;
611            case(GL_TRIANGLES): primLength=3; break;
612            case(GL_QUADS):     primLength=4; break;
613            default:            primLength=0; break; // compute later when =0.
614        }
615
616        // draw primtives by the more flexible "slow" path,
617        // sending OpenGL glBegin/glVertex.../glEnd().
618        switch(primitiveset->getType())
619        {
620            case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
621            {
622
623                const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
624                for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
625                    primItr!=drawArrayLengths->end();
626                    ++primItr)
627                {
628                    if (primLength==0) totalNumberOfPrimitives += 1;
629                    else totalNumberOfPrimitives += *primItr/primLength; // Dec 2003 - increment not set
630                }
631                break;
632            }
633            default:
634            {
635                if (primLength==0) totalNumberOfPrimitives += 1;
636                else totalNumberOfPrimitives += primitiveset->getNumIndices()/primLength;
637            }
638        }
639    }
640
641    return totalNumberOfPrimitives;
642}
643//
644void Tesselator::collectTesselation(osg::Geometry &geom)
645{
646    osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray());
647    VertexPtrToIndexMap vertexPtrToIndexMap;
648   
649    // populate the VertexPtrToIndexMap.
650    for(unsigned int vi=0;vi<vertices->size();++vi)
651    {
652        vertexPtrToIndexMap[&((*vertices)[vi])] = vi;
653    }
654   
655    handleNewVertices(geom, vertexPtrToIndexMap);
656   
657    // we don't properly handle per primitive and per primitive_set bindings yet
658    // will need to address this soon. Robert Oct 2002.
659    {
660        osg::Vec3Array* normals = NULL; // GWM Sep 2002 - add normals for extra facets
661        int iprim=0;
662        if (geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE ||
663            geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE_SET)
664        {
665            normals = geom.getNormalArray(); // GWM Sep 2002
666        }
667        // GWM Dec 2003 - needed to add colours for extra facets
668        osg::Vec4Array* cols4 = NULL; // GWM Dec 2003 colours are vec4
669        osg::Vec3Array* cols3 = NULL; // GWM Dec 2003 colours are vec3
670        if (geom.getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE ||
671              geom.getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE_SET)
672        {
673              Array* colours = geom.getColorArray(); // GWM Dec 2003 - need to duplicate face colours
674              switch (colours->getType()) {
675              case osg::Array::Vec4ArrayType:
676                  cols4=dynamic_cast<osg::Vec4Array *> (colours);
677                  break;
678              case osg::Array::Vec3ArrayType:
679                  cols3=dynamic_cast<osg::Vec3Array *> (colours);
680                  break;
681              default:
682                  break;
683              }
684             
685        }
686        // GWM Dec 2003 - these holders need to go outside the loop to
687        // retain the flat shaded colour &/or normal for each tesselated polygon
688        osg::Vec3 norm(0.0f,0.0f,0.0f);
689        osg::Vec4 primCol4(0.0f,0.0f,0.0f,1.0f);
690        osg::Vec3 primCol3(0.0f,0.0f,0.0f);
691
692        for(PrimList::iterator primItr=_primList.begin();
693        primItr!=_primList.end();
694        ++primItr, ++_index)
695        {
696              Prim* prim = primItr->get();
697             
698              osg::DrawElementsUShort* elements = new osg::DrawElementsUShort(prim->_mode);
699              for(Prim::VecList::iterator vitr=prim->_vertices.begin();
700              vitr!=prim->_vertices.end();
701              ++vitr)
702              {
703                  elements->push_back(vertexPtrToIndexMap[*vitr]);
704              }
705             
706              // add to the drawn primitive list.
707              geom.addPrimitiveSet(elements);
708              if (primItr==_primList.begin())
709              {   // first primitive so collect primitive normal & colour.
710                  if (normals) {
711                      norm=(*normals)[iprim]; // GWM Sep 2002 the flat shaded normal
712                  }
713                  if (cols4) {
714                      primCol4=(*cols4)[iprim]; // GWM Dec 2003 the flat shaded rgba colour
715                    if (_index>=cols4->size()) {
716                        cols4->push_back(primCol4); // GWM Dec 2003 add flat shaded colour for new facet
717                    }
718                  }
719                  if (cols3) {
720                      primCol3=(*cols3)[iprim]; // GWM Dec 2003 flat shaded rgb colour
721                    if (_index>=cols4->size()) {
722                        cols3->push_back(primCol3); // GWM Dec 2003 add flat shaded colour for new facet
723                    }
724                  }
725              }
726              else
727              { // later primitives use same colour
728                  if (normals) normals->push_back(norm); // GWM Sep 2002 add flat shaded normal for new facet
729                  if (cols4 && _index>=cols4->size()) {
730                    cols4->push_back(primCol4); // GWM Dec 2003 add flat shaded colour for new facet
731                  }
732                  if (cols3 && _index>=cols3->size()) {
733                    if (cols3) cols3->push_back(primCol3); // GWM Dec 2003 add flat shaded colour for new facet
734                  }
735                  if (prim->_mode==GL_TRIANGLES) {
736                      int ntris=elements->getNumIndices()/3;
737                      if (geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE_SET ||
738                          geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE) { // need one per triangle? Not one per set.
739                          for (int ii=1; ii<ntris; ii++) {
740                              if (normals) normals->push_back(norm); // GWM Sep 2002 add flat shaded normal for new facet
741                          }
742                      }
743                      if (geom.getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE_SET ||
744                          geom.getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE) { // need one per triangle? Not one per set.
745                          for (int ii=1; ii<ntris; ii++) {
746                              if (cols3 && _index>=cols3->size()) {
747                                  if (cols3) cols3->push_back(primCol3);
748                              }
749                              if (cols4 && _index>=cols4->size()) {
750                                  if (cols4) cols4->push_back(primCol4);
751                              }
752                              _index++;
753                          }
754                      }
755                  }
756                  //        osg::notify(osg::WARN)<<"Add: "<< iprim << std::endl;
757              }
758              iprim++; // GWM Sep 2002 count which normal we should use
759        }
760    }
761}
Note: See TracBrowser for help on using the browser.