root/OpenSceneGraph/trunk/src/osg/Geometry.cpp @ 13041

Revision 13041, 98.2 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 <stdlib.h>
14
15#include <osg/Geometry>
16#include <osg/ArrayDispatchers>
17#include <osg/Notify>
18
19using namespace osg;
20
21const Geometry::ArrayData Geometry::s_InvalidArrayData;
22
23Geometry::ArrayData::ArrayData(const ArrayData& data,const CopyOp& copyop):
24    array(copyop(data.array.get())),
25    indices(dynamic_cast<osg::IndexArray*>(copyop(data.indices.get()))),
26    binding(data.binding),
27    normalize(data.normalize)
28{
29}
30
31Geometry::Vec3ArrayData::Vec3ArrayData(const Vec3ArrayData& data,const CopyOp& copyop):
32    array(dynamic_cast<osg::Vec3Array*>(copyop(data.array.get()))),
33    indices(dynamic_cast<osg::IndexArray*>(copyop(data.indices.get()))),
34    binding(data.binding),
35    normalize(data.normalize)
36{
37}
38
39Geometry::Geometry()
40{
41    // temporary test
42    // setSupportsDisplayList(false);
43
44    _vertexData.binding = BIND_PER_VERTEX;
45
46    _fastPath = false;
47    _fastPathHint = true;
48}
49
50Geometry::Geometry(const Geometry& geometry,const CopyOp& copyop):
51    Drawable(geometry,copyop),
52    _vertexData(geometry._vertexData,copyop),
53    _normalData(geometry._normalData,copyop),
54    _colorData(geometry._colorData,copyop),
55    _secondaryColorData(geometry._secondaryColorData,copyop),
56    _fogCoordData(geometry._fogCoordData,copyop),
57    _fastPath(geometry._fastPath),
58    _fastPathHint(geometry._fastPathHint)
59{
60    // temporary test
61    // setSupportsDisplayList(false);
62
63    for(PrimitiveSetList::const_iterator pitr=geometry._primitives.begin();
64        pitr!=geometry._primitives.end();
65        ++pitr)
66    {
67        PrimitiveSet* primitive = copyop(pitr->get());
68        if (primitive) _primitives.push_back(primitive);
69    }
70
71    for(ArrayDataList::const_iterator titr=geometry._texCoordList.begin();
72        titr!=geometry._texCoordList.end();
73        ++titr)
74    {
75        _texCoordList.push_back(ArrayData(*titr, copyop));
76    }
77
78    for(ArrayDataList::const_iterator vitr=geometry._vertexAttribList.begin();
79        vitr!=geometry._vertexAttribList.end();
80        ++vitr)
81    {
82        _vertexAttribList.push_back(ArrayData(*vitr, copyop));
83    }
84
85    if ((copyop.getCopyFlags() & osg::CopyOp::DEEP_COPY_ARRAYS))
86    {
87        if (_useVertexBufferObjects)
88        {
89            // copying of arrays doesn't set up buffer objects so we'll need to force
90            // Geometry to assign these, we'll do this by switching off VBO's then renabling them.
91            setUseVertexBufferObjects(false);
92            setUseVertexBufferObjects(true);
93        }
94    }
95
96}
97
98Geometry::~Geometry()
99{
100    // do dirty here to keep the getGLObjectSizeHint() estimate on the ball
101    dirtyDisplayList();
102
103    // no need to delete, all automatically handled by ref_ptr :-)
104}
105
106bool Geometry::empty() const
107{
108    if (!_primitives.empty()) return false;
109    if (!_vertexData.empty()) return false;
110    if (!_normalData.empty()) return false;
111    if (!_colorData.empty()) return false;
112    if (!_secondaryColorData.empty()) return false;
113    if (!_fogCoordData.empty()) return false;
114    if (!_texCoordList.empty()) return false;
115    if (!_vertexAttribList.empty()) return false;
116    return true;
117}
118
119void Geometry::setVertexArray(Array* array)
120{
121    _vertexData.array = array;
122    computeFastPathsUsed();
123    dirtyDisplayList();
124    dirtyBound();
125
126    if (_useVertexBufferObjects && array) addVertexBufferObjectIfRequired(array);
127}
128
129void Geometry::setVertexIndices(IndexArray* array)
130{
131    _vertexData.indices = array;
132    computeFastPathsUsed();
133    dirtyDisplayList();
134    dirtyBound();
135}
136
137void Geometry::setVertexData(const ArrayData& arrayData)
138{
139    _vertexData = arrayData;
140    computeFastPathsUsed();
141    dirtyDisplayList();
142    dirtyBound();
143
144    if (_useVertexBufferObjects && arrayData.array.valid()) addVertexBufferObjectIfRequired(arrayData.array.get());
145}
146
147void Geometry::setNormalArray(Array* array)
148{
149    _normalData.array = array;
150    if (!_normalData.array.valid()) _normalData.binding=BIND_OFF;
151    computeFastPathsUsed();
152    dirtyDisplayList();
153
154    if (_useVertexBufferObjects && array) addVertexBufferObjectIfRequired(array);
155}
156
157void Geometry::setNormalIndices(IndexArray* array)
158{
159    _normalData.indices = array;
160    computeFastPathsUsed();
161    dirtyDisplayList();
162}
163
164void Geometry::setNormalData(const ArrayData& arrayData)
165{
166    _normalData = arrayData;
167    computeFastPathsUsed();
168    dirtyDisplayList();
169
170    if (_useVertexBufferObjects && arrayData.array.valid()) addVertexBufferObjectIfRequired(arrayData.array.get());
171}
172
173void Geometry::setColorArray(Array* array)
174{
175    _colorData.array = array;
176    if (!_colorData.array.valid()) _colorData.binding=BIND_OFF;
177    computeFastPathsUsed();
178    dirtyDisplayList();
179
180    if (_useVertexBufferObjects && array) addVertexBufferObjectIfRequired(array);
181}
182
183void Geometry::setColorIndices(IndexArray* array)
184{
185    _colorData.indices = array;
186    computeFastPathsUsed();
187    dirtyDisplayList();
188}
189
190void Geometry::setColorData(const ArrayData& arrayData)
191{
192    _colorData = arrayData;
193    computeFastPathsUsed();
194    dirtyDisplayList();
195
196    if (_useVertexBufferObjects && arrayData.array.valid()) addVertexBufferObjectIfRequired(arrayData.array.get());
197}
198
199
200void Geometry::setSecondaryColorArray(Array* array)
201{
202    _secondaryColorData.array = array;
203    if (!_secondaryColorData.array.valid()) _secondaryColorData.binding=BIND_OFF;
204    computeFastPathsUsed();
205    dirtyDisplayList();
206
207    if (_useVertexBufferObjects && array) addVertexBufferObjectIfRequired(array);
208}
209
210void Geometry::setSecondaryColorIndices(IndexArray* array)
211{
212    _secondaryColorData.indices = array;
213    computeFastPathsUsed();
214    dirtyDisplayList();
215}
216
217void Geometry::setSecondaryColorData(const ArrayData& arrayData)
218{
219    _secondaryColorData = arrayData;
220    computeFastPathsUsed();
221    dirtyDisplayList();
222
223    if (_useVertexBufferObjects && arrayData.array.valid()) addVertexBufferObjectIfRequired(arrayData.array.get());
224}
225
226void Geometry::setFogCoordArray(Array* array)
227{
228    _fogCoordData.array = array;
229    if (!_fogCoordData.array.valid()) _fogCoordData.binding=BIND_OFF;
230    computeFastPathsUsed();
231    dirtyDisplayList();
232
233    if (_useVertexBufferObjects && array) addVertexBufferObjectIfRequired(array);
234}
235
236void Geometry::setFogCoordIndices(IndexArray* array)
237{
238    _fogCoordData.indices = array;
239    computeFastPathsUsed();
240    dirtyDisplayList();
241}
242
243void Geometry::setFogCoordData(const ArrayData& arrayData)
244{
245    _fogCoordData = arrayData;
246    computeFastPathsUsed();
247    dirtyDisplayList();
248
249    if (_useVertexBufferObjects && arrayData.array.valid()) addVertexBufferObjectIfRequired(arrayData.array.get());
250}
251
252void Geometry::setNormalBinding(AttributeBinding ab)
253{
254    if (_normalData.binding == ab) return;
255
256    _normalData.binding = ab;
257    computeFastPathsUsed();
258    dirtyDisplayList();
259}
260
261void Geometry::setColorBinding(AttributeBinding ab)
262{
263    if (_colorData.binding == ab) return;
264
265    _colorData.binding = ab;
266    computeFastPathsUsed();
267    dirtyDisplayList();
268}
269
270void Geometry::setSecondaryColorBinding(AttributeBinding ab)
271{
272    if (_secondaryColorData.binding == ab) return;
273
274    _secondaryColorData.binding = ab;
275    computeFastPathsUsed();
276    dirtyDisplayList();
277}
278
279void Geometry::setFogCoordBinding(AttributeBinding ab)
280{
281    if (_fogCoordData.binding == ab) return;
282
283    _fogCoordData.binding = ab;
284    computeFastPathsUsed();
285    dirtyDisplayList();
286}
287
288void Geometry::setTexCoordData(unsigned int unit,const ArrayData& arrayData)
289{
290    if (_texCoordList.size()<=unit)
291        _texCoordList.resize(unit+1);
292
293    _texCoordList[unit] = arrayData;
294
295    if (_useVertexBufferObjects && arrayData.array.valid()) addVertexBufferObjectIfRequired(arrayData.array.get());
296}
297
298Geometry::ArrayData& Geometry::getTexCoordData(unsigned int unit)
299{
300    if (_texCoordList.size()<=unit)
301        _texCoordList.resize(unit+1);
302
303    return _texCoordList[unit];
304}
305
306const Geometry::ArrayData& Geometry::getTexCoordData(unsigned int unit) const
307{
308    if (_texCoordList.size()<=unit)
309        return s_InvalidArrayData;
310
311    return _texCoordList[unit];
312}
313
314void Geometry::setTexCoordArray(unsigned int unit,Array* array)
315{
316    getTexCoordData(unit).binding = BIND_PER_VERTEX;
317    getTexCoordData(unit).array = array;
318
319    computeFastPathsUsed();
320    dirtyDisplayList();
321
322    if (_useVertexBufferObjects && array)
323    {
324        addVertexBufferObjectIfRequired(array);
325    }
326}
327
328Array* Geometry::getTexCoordArray(unsigned int unit)
329{
330    if (unit<_texCoordList.size()) return _texCoordList[unit].array.get();
331    else return 0;
332}
333
334const Array* Geometry::getTexCoordArray(unsigned int unit) const
335{
336    if (unit<_texCoordList.size()) return _texCoordList[unit].array.get();
337    else return 0;
338}
339
340void Geometry::setTexCoordIndices(unsigned int unit,IndexArray* array)
341{
342    getTexCoordData(unit).indices = array;
343
344    computeFastPathsUsed();
345    dirtyDisplayList();
346}
347
348IndexArray* Geometry::getTexCoordIndices(unsigned int unit)
349{
350    if (unit<_texCoordList.size()) return _texCoordList[unit].indices.get();
351    else return 0;
352}
353
354const IndexArray* Geometry::getTexCoordIndices(unsigned int unit) const
355{
356    if (unit<_texCoordList.size()) return _texCoordList[unit].indices.get();
357    else return 0;
358}
359
360
361void Geometry::setVertexAttribData(unsigned int index, const Geometry::ArrayData& attrData)
362{
363    if (_vertexAttribList.size()<=index)
364        _vertexAttribList.resize(index+1);
365
366    _vertexAttribList[index] = attrData;
367
368    computeFastPathsUsed();
369    dirtyDisplayList();
370
371    if (_useVertexBufferObjects && attrData.array.valid()) addVertexBufferObjectIfRequired(attrData.array.get());
372}
373
374Geometry::ArrayData& Geometry::getVertexAttribData(unsigned int index)
375{
376    if (_vertexAttribList.size()<=index)
377        _vertexAttribList.resize(index+1);
378
379    return _vertexAttribList[index];
380}
381
382const Geometry::ArrayData& Geometry::getVertexAttribData(unsigned int index) const
383{
384    if (_vertexAttribList.size()<=_vertexAttribList.size())
385        return s_InvalidArrayData;
386
387    return _vertexAttribList[index];
388}
389
390void Geometry::setVertexAttribArray(unsigned int index, Array* array)
391{
392    getVertexAttribData(index).array = array;
393
394    computeFastPathsUsed();
395    dirtyDisplayList();
396
397    if (_useVertexBufferObjects && array) addVertexBufferObjectIfRequired(array);
398}
399
400Array *Geometry::getVertexAttribArray(unsigned int index)
401{
402    if (index<_vertexAttribList.size()) return _vertexAttribList[index].array.get();
403    else return 0;
404}
405
406const Array *Geometry::getVertexAttribArray(unsigned int index) const
407{
408    if (index<_vertexAttribList.size()) return _vertexAttribList[index].array.get();
409    else return 0;
410}
411
412void Geometry::setVertexAttribIndices(unsigned int index,IndexArray* array)
413{
414    getVertexAttribData(index).indices = array;
415
416    computeFastPathsUsed();
417    dirtyDisplayList();
418}
419
420IndexArray* Geometry::getVertexAttribIndices(unsigned int index)
421{
422    if (index<_vertexAttribList.size()) return _vertexAttribList[index].indices.get();
423    else return 0;
424}
425
426const IndexArray* Geometry::getVertexAttribIndices(unsigned int index) const
427{
428    if (index<_vertexAttribList.size()) return _vertexAttribList[index].indices.get();
429    else return 0;
430}
431
432void Geometry::setVertexAttribBinding(unsigned int index,AttributeBinding ab)
433{
434    if (getVertexAttribData(index).binding == ab)
435       return;
436    getVertexAttribData(index).binding = ab;
437    computeFastPathsUsed();
438    dirtyDisplayList();
439}
440
441Geometry::AttributeBinding Geometry::getVertexAttribBinding(unsigned int index) const
442{
443    if (index<_vertexAttribList.size()) return _vertexAttribList[index].binding;
444    else return BIND_OFF;
445}
446
447void Geometry::setVertexAttribNormalize(unsigned int index,GLboolean norm)
448{
449    getVertexAttribData(index).normalize = norm;
450
451    dirtyDisplayList();
452}
453
454GLboolean Geometry::getVertexAttribNormalize(unsigned int index) const
455{
456    if (index<_vertexAttribList.size()) return _vertexAttribList[index].normalize;
457    else return GL_FALSE;
458}
459
460bool Geometry::addPrimitiveSet(PrimitiveSet* primitiveset)
461{
462    if (primitiveset)
463    {
464        if (_useVertexBufferObjects) addElementBufferObjectIfRequired(primitiveset);
465
466        _primitives.push_back(primitiveset);
467        dirtyDisplayList();
468        dirtyBound();
469        return true;
470    }
471    OSG_WARN<<"Warning: invalid index i or primitiveset passed to osg::Geometry::addPrimitiveSet(i,primitiveset), ignoring call."<<std::endl;
472    return false;
473}
474
475bool Geometry::setPrimitiveSet(unsigned int i,PrimitiveSet* primitiveset)
476{
477    if (i<_primitives.size() && primitiveset)
478    {
479        if (_useVertexBufferObjects) addElementBufferObjectIfRequired(primitiveset);
480
481        _primitives[i] = primitiveset;
482        dirtyDisplayList();
483        dirtyBound();
484        return true;
485    }
486    OSG_WARN<<"Warning: invalid index i or primitiveset passed to osg::Geometry::setPrimitiveSet(i,primitiveset), ignoring call."<<std::endl;
487    return false;
488}
489
490bool Geometry::insertPrimitiveSet(unsigned int i,PrimitiveSet* primitiveset)
491{
492
493    if (primitiveset)
494    {
495        if (_useVertexBufferObjects) addElementBufferObjectIfRequired(primitiveset);
496
497        if (i<_primitives.size())
498        {
499            _primitives.insert(_primitives.begin()+i,primitiveset);
500            dirtyDisplayList();
501            dirtyBound();
502            return true;
503        }
504        else if (i==_primitives.size())
505        {
506            return addPrimitiveSet(primitiveset);
507        }
508
509    }
510    OSG_WARN<<"Warning: invalid index i or primitiveset passed to osg::Geometry::insertPrimitiveSet(i,primitiveset), ignoring call."<<std::endl;
511    return false;
512}
513
514void Geometry::setPrimitiveSetList(const PrimitiveSetList& primitives)
515{
516    _primitives = primitives;
517    if (_useVertexBufferObjects)
518    {
519        for (unsigned int primitiveSetIndex=0;primitiveSetIndex<_primitives.size();++primitiveSetIndex)
520        {
521            addElementBufferObjectIfRequired(_primitives[primitiveSetIndex].get());
522        }
523
524    }
525    dirtyDisplayList(); dirtyBound();
526}
527
528bool Geometry::removePrimitiveSet(unsigned int i, unsigned int numElementsToRemove)
529{
530    if (numElementsToRemove==0) return false;
531
532    if (i<_primitives.size())
533    {
534        if (i+numElementsToRemove<=_primitives.size())
535        {
536            _primitives.erase(_primitives.begin()+i,_primitives.begin()+i+numElementsToRemove);
537        }
538        else
539        {
540            // asking to delete too many elements, report a warning, and delete to
541            // the end of the primitive list.
542            OSG_WARN<<"Warning: osg::Geometry::removePrimitiveSet(i,numElementsToRemove) has been asked to remove more elements than are available,"<<std::endl;
543            OSG_WARN<<"         removing on from i to the end of the list of primitive sets."<<std::endl;
544            _primitives.erase(_primitives.begin()+i,_primitives.end());
545        }
546
547        dirtyDisplayList();
548        dirtyBound();
549        return true;
550    }
551    OSG_WARN<<"Warning: invalid index i passed to osg::Geometry::removePrimitiveSet(i,numElementsToRemove), ignoring call."<<std::endl;
552    return false;
553}
554
555unsigned int Geometry::getPrimitiveSetIndex(const PrimitiveSet* primitiveset) const
556{
557    for (unsigned int primitiveSetIndex=0;primitiveSetIndex<_primitives.size();++primitiveSetIndex)
558    {
559        if (_primitives[primitiveSetIndex]==primitiveset) return primitiveSetIndex;
560    }
561    return _primitives.size(); // node not found.
562}
563
564bool Geometry::computeFastPathsUsed()
565{
566    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
567    //
568    // check to see if fast path can be used.
569    //
570    _fastPath = true;
571    if (_vertexData.indices.valid()) _fastPath = false;
572    else if (_normalData.binding==BIND_PER_PRIMITIVE || (_normalData.binding==BIND_PER_VERTEX && _normalData.indices.valid())) _fastPath = false;
573    else if (_colorData.binding==BIND_PER_PRIMITIVE || (_colorData.binding==BIND_PER_VERTEX && _colorData.indices.valid())) _fastPath = false;
574    else if (_secondaryColorData.binding==BIND_PER_PRIMITIVE || (_secondaryColorData.binding==BIND_PER_VERTEX && _secondaryColorData.indices.valid())) _fastPath = false;
575    else if (_fogCoordData.binding==BIND_PER_PRIMITIVE || (_fogCoordData.binding==BIND_PER_VERTEX && _fogCoordData.indices.valid())) _fastPath = false;
576    else
577    {
578        for( unsigned int va = 0; va < _vertexAttribList.size(); ++va )
579        {
580            if (_vertexAttribList[va].binding==BIND_PER_PRIMITIVE)
581            {
582                _fastPath = false;
583                break;
584            }
585            else
586            {
587                const Array * array = _vertexAttribList[va].array.get();
588                const IndexArray * idxArray = _vertexAttribList[va].indices.get();
589
590                if( _vertexAttribList[va].binding==BIND_PER_VERTEX &&
591                    array && array->getNumElements()>0 &&
592                    idxArray && idxArray->getNumElements()>0 )
593                {
594                    _fastPath = false;
595                    break;
596                }
597            }
598        }
599    }
600
601    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
602    //
603    // Set up tex coords if required.
604    //
605    for(unsigned int unit=0;unit<_texCoordList.size();++unit)
606    {
607        const ArrayData& texcoordData = _texCoordList[unit];
608        if (texcoordData.array.valid() && texcoordData.array->getNumElements()>0)
609        {
610            if (texcoordData.indices.valid())
611            {
612                if (texcoordData.indices->getNumElements()>0)
613                {
614                    _fastPath = false;
615                    break;
616                }
617            }
618        }
619    }
620
621    _supportsVertexBufferObjects = _fastPath;
622
623    //_supportsVertexBufferObjects = false;
624    //_useVertexBufferObjects = false;
625
626    return _fastPath;
627}
628
629unsigned int Geometry::getGLObjectSizeHint() const
630{
631    unsigned int totalSize = 0;
632    if (_vertexData.array.valid()) totalSize += _vertexData.array->getTotalDataSize();
633
634    if (_normalData.array.valid()) totalSize += _normalData.array->getTotalDataSize();
635
636    if (_colorData.array.valid()) totalSize += _colorData.array->getTotalDataSize();
637
638    if (_secondaryColorData.array.valid()) totalSize += _secondaryColorData.array->getTotalDataSize();
639
640    if (_fogCoordData.array.valid()) totalSize += _fogCoordData.array->getTotalDataSize();
641
642
643    unsigned int unit;
644    for(unit=0;unit<_texCoordList.size();++unit)
645    {
646        const Array* array = _texCoordList[unit].array.get();
647        if (array) totalSize += array->getTotalDataSize();
648
649    }
650
651    bool handleVertexAttributes = true;
652    if (handleVertexAttributes)
653    {
654        unsigned int index;
655        for( index = 0; index < _vertexAttribList.size(); ++index )
656        {
657            const Array* array = _vertexAttribList[index].array.get();
658            if (array) totalSize += array->getTotalDataSize();
659        }
660    }
661
662    for(PrimitiveSetList::const_iterator itr=_primitives.begin();
663        itr!=_primitives.end();
664        ++itr)
665    {
666
667        totalSize += 4*(*itr)->getNumIndices();
668
669    }
670
671
672    // do a very simply mapping of display list size proportional to vertex datasize.
673    return totalSize;
674}
675
676bool Geometry::getArrayList(ArrayList& arrayList) const
677{
678    unsigned int startSize = arrayList.size();
679
680    if (_vertexData.array.valid()) arrayList.push_back(_vertexData.array.get());
681    if (_normalData.array.valid()) arrayList.push_back(_normalData.array.get());
682    if (_colorData.array.valid()) arrayList.push_back(_colorData.array.get());
683    if (_secondaryColorData.array.valid()) arrayList.push_back(_secondaryColorData.array.get());
684    if (_fogCoordData.array.valid()) arrayList.push_back(_fogCoordData.array.get());
685
686    for(unsigned int unit=0;unit<_texCoordList.size();++unit)
687    {
688        Array* array = _texCoordList[unit].array.get();
689        if (array) arrayList.push_back(array);
690    }
691
692    for(unsigned int  index = 0; index < _vertexAttribList.size(); ++index )
693    {
694        Array* array = _vertexAttribList[index].array.get();
695        if (array) arrayList.push_back(array);
696    }
697
698    return arrayList.size()!=startSize;
699}
700
701bool Geometry::getDrawElementsList(DrawElementsList& drawElementsList) const
702{
703    unsigned int startSize = drawElementsList.size();
704
705    for(PrimitiveSetList::const_iterator itr = _primitives.begin();
706        itr != _primitives.end();
707        ++itr)
708    {
709        osg::DrawElements* de = (*itr)->getDrawElements();
710        if (de) drawElementsList.push_back(de);
711    }
712
713    return drawElementsList.size()!=startSize;
714}
715
716void Geometry::addVertexBufferObjectIfRequired(osg::Array* array)
717{
718    if (_useVertexBufferObjects)
719    {
720        if (!array->getVertexBufferObject())
721        {
722            array->setVertexBufferObject(getOrCreateVertexBufferObject());
723        }
724    }
725}
726
727void Geometry::addElementBufferObjectIfRequired(osg::PrimitiveSet* primitiveSet)
728{
729    if (_useVertexBufferObjects)
730    {
731        osg::DrawElements* drawElements = primitiveSet->getDrawElements();
732        if (drawElements && !drawElements->getElementBufferObject())
733        {
734            drawElements->setElementBufferObject(getOrCreateElementBufferObject());
735        }
736    }
737}
738
739osg::VertexBufferObject* Geometry::getOrCreateVertexBufferObject()
740{
741    ArrayList arrayList;
742    getArrayList(arrayList);
743
744    ArrayList::iterator vitr;
745    for(vitr = arrayList.begin();
746        vitr != arrayList.end();
747        ++vitr)
748    {
749        osg::Array* array = *vitr;
750        if (array->getVertexBufferObject()) return array->getVertexBufferObject();
751    }
752
753    return new osg::VertexBufferObject;
754}
755
756osg::ElementBufferObject* Geometry::getOrCreateElementBufferObject()
757{
758    DrawElementsList drawElementsList;
759    getDrawElementsList(drawElementsList);
760
761    DrawElementsList::iterator deitr;
762    for(deitr = drawElementsList.begin();
763        deitr != drawElementsList.end();
764        ++deitr)
765    {
766        osg::DrawElements* elements = *deitr;
767        if (elements->getElementBufferObject()) return elements->getElementBufferObject();
768    }
769
770    return new osg::ElementBufferObject;
771}
772
773void Geometry::setUseVertexBufferObjects(bool flag)
774{
775    // flag = true;
776
777    // OSG_NOTICE<<"Geometry::setUseVertexBufferObjects("<<flag<<")"<<std::endl;
778
779    if (_useVertexBufferObjects==flag) return;
780
781    Drawable::setUseVertexBufferObjects(flag);
782
783    ArrayList arrayList;
784    getArrayList(arrayList);
785
786    DrawElementsList drawElementsList;
787    getDrawElementsList(drawElementsList);
788
789    typedef std::vector<osg::VertexBufferObject*>  VertexBufferObjectList;
790    typedef std::vector<osg::ElementBufferObject*>  ElementBufferObjectList;
791
792    if (_useVertexBufferObjects)
793    {
794        if (!arrayList.empty())
795        {
796
797            VertexBufferObjectList vboList;
798
799            osg::ref_ptr<osg::VertexBufferObject> vbo;
800
801            ArrayList::iterator vitr;
802            for(vitr = arrayList.begin();
803                vitr != arrayList.end() && !vbo;
804                ++vitr)
805            {
806                osg::Array* array = *vitr;
807                if (array->getVertexBufferObject()) vbo = array->getVertexBufferObject();
808            }
809
810            if (!vbo) vbo = new osg::VertexBufferObject;
811
812            for(vitr = arrayList.begin();
813                vitr != arrayList.end();
814                ++vitr)
815            {
816                osg::Array* array = *vitr;
817                if (!array->getVertexBufferObject()) array->setVertexBufferObject(vbo.get());
818            }
819        }
820
821        if (!drawElementsList.empty())
822        {
823            ElementBufferObjectList eboList;
824
825            osg::ref_ptr<osg::ElementBufferObject> ebo;
826
827            DrawElementsList::iterator deitr;
828            for(deitr = drawElementsList.begin();
829                deitr != drawElementsList.end();
830                ++deitr)
831            {
832                osg::DrawElements* elements = *deitr;
833                if (elements->getElementBufferObject()) ebo = elements->getElementBufferObject();
834            }
835
836            if (!ebo) ebo = new osg::ElementBufferObject;
837
838            for(deitr = drawElementsList.begin();
839                deitr != drawElementsList.end();
840                ++deitr)
841            {
842                osg::DrawElements* elements = *deitr;
843                if (!elements->getElementBufferObject()) elements->setElementBufferObject(ebo.get());
844            }
845        }
846    }
847    else
848    {
849        for(ArrayList::iterator vitr = arrayList.begin();
850            vitr != arrayList.end();
851            ++vitr)
852        {
853            osg::Array* array = *vitr;
854            if (array->getVertexBufferObject()) array->setVertexBufferObject(0);
855        }
856
857        for(DrawElementsList::iterator deitr = drawElementsList.begin();
858            deitr != drawElementsList.end();
859            ++deitr)
860        {
861            osg::DrawElements* elements = *deitr;
862            if (elements->getElementBufferObject()) elements->setElementBufferObject(0);
863        }
864    }
865}
866
867void Geometry::dirtyDisplayList()
868{
869    Drawable::dirtyDisplayList();
870}
871
872void Geometry::resizeGLObjectBuffers(unsigned int maxSize)
873{
874    Drawable::resizeGLObjectBuffers(maxSize);
875
876    ArrayList arrays;
877    if (getArrayList(arrays))
878    {
879        for(ArrayList::iterator itr = arrays.begin();
880            itr != arrays.end();
881            ++itr)
882        {
883            (*itr)->resizeGLObjectBuffers(maxSize);
884        }
885    }
886
887    DrawElementsList drawElements;
888    if (getDrawElementsList(drawElements))
889    {
890        for(DrawElementsList::iterator itr = drawElements.begin();
891            itr != drawElements.end();
892            ++itr)
893        {
894            (*itr)->resizeGLObjectBuffers(maxSize);
895        }
896    }
897}
898
899void Geometry::releaseGLObjects(State* state) const
900{
901    Drawable::releaseGLObjects(state);
902
903    ArrayList arrays;
904    if (getArrayList(arrays))
905    {
906        for(ArrayList::iterator itr = arrays.begin();
907            itr != arrays.end();
908            ++itr)
909        {
910            (*itr)->releaseGLObjects(state);
911        }
912    }
913
914    DrawElementsList drawElements;
915    if (getDrawElementsList(drawElements))
916    {
917        for(DrawElementsList::iterator itr = drawElements.begin();
918            itr != drawElements.end();
919            ++itr)
920        {
921            (*itr)->releaseGLObjects(state);
922        }
923    }
924
925}
926
927void Geometry::compileGLObjects(RenderInfo& renderInfo) const
928{
929    bool useVertexArrays = _supportsVertexBufferObjects &&
930                           _useVertexBufferObjects &&
931                           renderInfo.getState()->isVertexBufferObjectSupported() &&
932                           areFastPathsUsed();
933    if (useVertexArrays)
934    {
935        // OSG_NOTICE<<"Geometry::compileGLObjects() use VBO's "<<this<<std::endl;
936        State& state = *renderInfo.getState();
937        unsigned int contextID = state.getContextID();
938        GLBufferObject::Extensions* extensions = GLBufferObject::getExtensions(contextID, true);
939        if (!extensions) return;
940
941        typedef std::set<BufferObject*> BufferObjects;
942        BufferObjects bufferObjects;
943
944        // first collect all the active unique BufferObjects
945        if (_vertexData.array.valid() && _vertexData.array->getBufferObject()) bufferObjects.insert(_vertexData.array->getBufferObject());
946        if (_normalData.array.valid() && _normalData.array->getBufferObject()) bufferObjects.insert(_normalData.array->getBufferObject());
947        if (_colorData.array.valid() && _colorData.array->getBufferObject()) bufferObjects.insert(_colorData.array->getBufferObject());
948        if (_secondaryColorData.array.valid() && _secondaryColorData.array->getBufferObject()) bufferObjects.insert(_secondaryColorData.array->getBufferObject());
949        if (_fogCoordData.array.valid() && _fogCoordData.array->getBufferObject()) bufferObjects.insert(_fogCoordData.array->getBufferObject());
950
951        for(ArrayDataList::const_iterator itr = _texCoordList.begin();
952            itr != _texCoordList.end();
953            ++itr)
954        {
955            if (itr->array.valid() && itr->array->getBufferObject()) bufferObjects.insert(itr->array->getBufferObject());
956        }
957
958        for(ArrayDataList::const_iterator itr = _vertexAttribList.begin();
959            itr != _vertexAttribList.end();
960            ++itr)
961        {
962            if (itr->array.valid() && itr->array->getBufferObject()) bufferObjects.insert(itr->array->getBufferObject());
963        }
964
965        for(PrimitiveSetList::const_iterator itr = _primitives.begin();
966            itr != _primitives.end();
967            ++itr)
968        {
969            if ((*itr)->getBufferObject()) bufferObjects.insert((*itr)->getBufferObject());
970        }
971
972        //osg::ElapsedTime timer;
973
974        // now compile any buffer objects that require it.
975        for(BufferObjects::iterator itr = bufferObjects.begin();
976            itr != bufferObjects.end();
977            ++itr)
978        {
979            GLBufferObject* glBufferObject = (*itr)->getOrCreateGLBufferObject(contextID);
980            if (glBufferObject && glBufferObject->isDirty())
981            {
982                // OSG_NOTICE<<"Compile buffer "<<glBufferObject<<std::endl;
983                glBufferObject->compileBuffer();
984            }
985        }
986
987        // OSG_NOTICE<<"Time to compile "<<timer.elapsedTime_m()<<"ms"<<std::endl;
988
989        // unbind the BufferObjects
990        extensions->glBindBuffer(GL_ARRAY_BUFFER_ARB,0);
991        extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB,0);
992
993    }
994    else
995    {
996        Drawable::compileGLObjects(renderInfo);
997    }
998}
999
1000void Geometry::drawImplementation(RenderInfo& renderInfo) const
1001{
1002#if 0
1003    if (!validGeometry())
1004    {
1005        OSG_NOTICE<<"Error, osg::Geometry has invalid array/primitive set usage"<<std::endl;
1006        return;
1007    }
1008#endif
1009
1010    if (_internalOptimizedGeometry.valid())
1011    {
1012        _internalOptimizedGeometry->drawImplementation(renderInfo);
1013        return;
1014    }
1015
1016    State& state = *renderInfo.getState();
1017
1018    bool checkForGLErrors = state.getCheckForGLErrors()==osg::State::ONCE_PER_ATTRIBUTE;
1019    if (checkForGLErrors) state.checkGLErrors("start of Geometry::drawImplementation()");
1020
1021    bool useFastPath = areFastPathsUsed();
1022    // useFastPath = false;
1023
1024    bool usingVertexBufferObjects = _useVertexBufferObjects && state.isVertexBufferObjectSupported();
1025    bool handleVertexAttributes = !_vertexAttribList.empty();
1026
1027    ArrayDispatchers& arrayDispatchers = state.getArrayDispatchers();
1028
1029    arrayDispatchers.reset();
1030    arrayDispatchers.setUseVertexAttribAlias(useFastPath && state.getUseVertexAttributeAliasing());
1031    arrayDispatchers.setUseGLBeginEndAdapter(!useFastPath);
1032
1033    arrayDispatchers.activateNormalArray(_normalData.binding, _normalData.array.get(), _normalData.indices.get());
1034    arrayDispatchers.activateColorArray(_colorData.binding, _colorData.array.get(), _colorData.indices.get());
1035    arrayDispatchers.activateSecondaryColorArray(_secondaryColorData.binding, _secondaryColorData.array.get(), _secondaryColorData.indices.get());
1036    arrayDispatchers.activateFogCoordArray(_fogCoordData.binding, _fogCoordData.array.get(), _fogCoordData.indices.get());
1037
1038    if (handleVertexAttributes)
1039    {
1040        for(unsigned int unit=0;unit<_vertexAttribList.size();++unit)
1041        {
1042            arrayDispatchers.activateVertexAttribArray(_vertexAttribList[unit].binding, unit, _vertexAttribList[unit].array.get(), _vertexAttribList[unit].indices.get());
1043        }
1044    }
1045
1046    // dispatch any attributes that are bound overall
1047    arrayDispatchers.dispatch(BIND_OVERALL,0);
1048
1049    state.lazyDisablingOfVertexAttributes();
1050
1051    if (useFastPath)
1052    {
1053        // set up arrays
1054        if( _vertexData.array.valid() )
1055            state.setVertexPointer(_vertexData.array.get());
1056
1057        if (_normalData.binding==BIND_PER_VERTEX && _normalData.array.valid())
1058            state.setNormalPointer(_normalData.array.get());
1059
1060        if (_colorData.binding==BIND_PER_VERTEX && _colorData.array.valid())
1061            state.setColorPointer(_colorData.array.get());
1062
1063        if (_secondaryColorData.binding==BIND_PER_VERTEX && _secondaryColorData.array.valid())
1064            state.setSecondaryColorPointer(_secondaryColorData.array.get());
1065
1066        if (_fogCoordData.binding==BIND_PER_VERTEX && _fogCoordData.array.valid())
1067            state.setFogCoordPointer(_fogCoordData.array.get());
1068
1069        for(unsigned int unit=0;unit<_texCoordList.size();++unit)
1070        {
1071            const Array* array = _texCoordList[unit].array.get();
1072            if (array) state.setTexCoordPointer(unit,array);
1073        }
1074
1075        if( handleVertexAttributes )
1076        {
1077            for(unsigned int index = 0; index < _vertexAttribList.size(); ++index )
1078            {
1079                const Array* array = _vertexAttribList[index].array.get();
1080                const AttributeBinding ab = _vertexAttribList[index].binding;
1081                if( ab == BIND_PER_VERTEX && array )
1082                {
1083                    state.setVertexAttribPointer( index, array, _vertexAttribList[index].normalize );
1084                }
1085            }
1086        }
1087    }
1088    else
1089    {
1090        for(unsigned int unit=0;unit<_texCoordList.size();++unit)
1091        {
1092            arrayDispatchers.activateTexCoordArray(BIND_PER_VERTEX, unit, _texCoordList[unit].array.get(), _texCoordList[unit].indices.get());
1093        }
1094
1095        arrayDispatchers.activateVertexArray(BIND_PER_VERTEX, _vertexData.array.get(), _vertexData.indices.get());
1096    }
1097
1098    state.applyDisablingOfVertexAttributes();
1099
1100    bool bindPerPrimitiveSetActive = arrayDispatchers.active(BIND_PER_PRIMITIVE_SET);
1101    bool bindPerPrimitiveActive = arrayDispatchers.active(BIND_PER_PRIMITIVE);
1102
1103    unsigned int primitiveNum = 0;
1104
1105    if (checkForGLErrors) state.checkGLErrors("Geometry::drawImplementation() after vertex arrays setup.");
1106
1107
1108    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1109    //
1110    // draw the primitives themselves.
1111    //
1112    for(unsigned int primitiveSetNum=0; primitiveSetNum!=_primitives.size(); ++primitiveSetNum)
1113    {
1114
1115        // dispatch any attributes that are bound per primitive
1116        if (bindPerPrimitiveSetActive) arrayDispatchers.dispatch(BIND_PER_PRIMITIVE_SET, primitiveSetNum);
1117
1118        const PrimitiveSet* primitiveset = _primitives[primitiveSetNum].get();
1119
1120        if (useFastPath)
1121        {
1122            primitiveset->draw(state, usingVertexBufferObjects);
1123        }
1124        else
1125        {
1126            GLenum mode=primitiveset->getMode();
1127
1128            unsigned int primLength;
1129            switch(mode)
1130            {
1131                case(GL_POINTS):    primLength=1; break;
1132                case(GL_LINES):     primLength=2; break;
1133                case(GL_TRIANGLES): primLength=3; break;
1134                case(GL_QUADS):     primLength=4; break;
1135                default:            primLength=0; break; // compute later when =0.
1136            }
1137
1138            // draw primitives by the more flexible "slow" path,
1139            // sending OpenGL glBegin/glVertex.../glEnd().
1140            switch(primitiveset->getType())
1141            {
1142                case(PrimitiveSet::DrawArraysPrimitiveType):
1143                {
1144                    if (primLength==0) primLength=primitiveset->getNumIndices();
1145
1146                    const DrawArrays* drawArray = static_cast<const DrawArrays*>(primitiveset);
1147                    arrayDispatchers.Begin(mode);
1148
1149                    unsigned int primCount=0;
1150                    unsigned int indexEnd = drawArray->getFirst()+drawArray->getCount();
1151                    for(unsigned int vindex=drawArray->getFirst();
1152                        vindex<indexEnd;
1153                        ++vindex,++primCount)
1154                    {
1155                        if (bindPerPrimitiveActive && (primCount%primLength)==0)
1156                        {
1157                            arrayDispatchers.dispatch(BIND_PER_PRIMITIVE,primitiveNum++);
1158                        }
1159
1160                        arrayDispatchers.dispatch(BIND_PER_VERTEX, vindex);
1161                    }
1162
1163                    arrayDispatchers.End();
1164                    break;
1165                }
1166                case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
1167                {
1168                    const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
1169                    unsigned int vindex=drawArrayLengths->getFirst();
1170                    for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
1171                        primItr!=drawArrayLengths->end();
1172                        ++primItr)
1173                    {
1174                        unsigned int localPrimLength;
1175                        if (primLength==0) localPrimLength=*primItr;
1176                        else localPrimLength=primLength;
1177
1178                        arrayDispatchers.Begin(mode);
1179
1180                        for(GLsizei primCount=0;
1181                            primCount<*primItr;
1182                            ++vindex,++primCount)
1183                        {
1184                            if (bindPerPrimitiveActive && (primCount%localPrimLength)==0)
1185                            {
1186                                arrayDispatchers.dispatch(BIND_PER_PRIMITIVE, primitiveNum++);
1187                            }
1188                            arrayDispatchers.dispatch(BIND_PER_VERTEX, vindex);
1189                        }
1190
1191                        arrayDispatchers.End();
1192
1193                    }
1194                    break;
1195                }
1196                case(PrimitiveSet::DrawElementsUBytePrimitiveType):
1197                {
1198                    if (primLength==0) primLength=primitiveset->getNumIndices();
1199
1200                    const DrawElementsUByte* drawElements = static_cast<const DrawElementsUByte*>(primitiveset);
1201                    arrayDispatchers.Begin(mode);
1202
1203                    unsigned int primCount=0;
1204                    for(DrawElementsUByte::const_iterator primItr=drawElements->begin();
1205                        primItr!=drawElements->end();
1206                        ++primCount,++primItr)
1207                    {
1208
1209                        if (bindPerPrimitiveActive && (primCount%primLength)==0)
1210                        {
1211                            arrayDispatchers.dispatch(BIND_PER_PRIMITIVE, primitiveNum++);
1212                        }
1213
1214                        unsigned int vindex=*primItr;
1215                        arrayDispatchers.dispatch(BIND_PER_VERTEX, vindex);
1216                    }
1217
1218                    arrayDispatchers.End();
1219                    break;
1220                }
1221                case(PrimitiveSet::DrawElementsUShortPrimitiveType):
1222                {
1223                    if (primLength==0) primLength=primitiveset->getNumIndices();
1224
1225                    const DrawElementsUShort* drawElements = static_cast<const DrawElementsUShort*>(primitiveset);
1226                    arrayDispatchers.Begin(mode);
1227
1228                    unsigned int primCount=0;
1229                    for(DrawElementsUShort::const_iterator primItr=drawElements->begin();
1230                        primItr!=drawElements->end();
1231                        ++primCount,++primItr)
1232                    {
1233                        if (bindPerPrimitiveActive && (primCount%primLength)==0)
1234                        {
1235                            arrayDispatchers.dispatch(BIND_PER_PRIMITIVE, primitiveNum++);
1236                        }
1237
1238                        unsigned int vindex=*primItr;
1239                        arrayDispatchers.dispatch(BIND_PER_VERTEX, vindex);
1240                    }
1241
1242                    arrayDispatchers.End();
1243                    break;
1244                }
1245                case(PrimitiveSet::DrawElementsUIntPrimitiveType):
1246                {
1247                    if (primLength==0) primLength=primitiveset->getNumIndices();
1248
1249                    const DrawElementsUInt* drawElements = static_cast<const DrawElementsUInt*>(primitiveset);
1250                    arrayDispatchers.Begin(mode);
1251
1252                    unsigned int primCount=0;
1253                    for(DrawElementsUInt::const_iterator primItr=drawElements->begin();
1254                        primItr!=drawElements->end();
1255                        ++primCount,++primItr)
1256                    {
1257                        if (bindPerPrimitiveActive && (primCount%primLength)==0)
1258                        {
1259                            arrayDispatchers.dispatch(BIND_PER_PRIMITIVE, primitiveNum++);
1260                        }
1261
1262                        unsigned int vindex=*primItr;
1263                        arrayDispatchers.dispatch(BIND_PER_VERTEX, vindex);
1264                    }
1265
1266                    arrayDispatchers.End();
1267                    break;
1268                }
1269                default:
1270                {
1271                    break;
1272                }
1273            }
1274        }
1275    }
1276
1277    // unbind the VBO's if any are used.
1278    state.unbindVertexBufferObject();
1279    state.unbindElementBufferObject();
1280
1281    if (checkForGLErrors) state.checkGLErrors("end of Geometry::drawImplementation().");
1282}
1283
1284class AttributeFunctorArrayVisitor : public ArrayVisitor
1285{
1286    public:
1287
1288        AttributeFunctorArrayVisitor(Drawable::AttributeFunctor& af):
1289            _af(af),
1290            _type(0) {}
1291
1292        virtual ~AttributeFunctorArrayVisitor() {}
1293
1294        virtual void apply(ByteArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1295        virtual void apply(ShortArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1296        virtual void apply(IntArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1297        virtual void apply(UByteArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1298        virtual void apply(UShortArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1299        virtual void apply(UIntArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1300        virtual void apply(Vec4ubArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1301        virtual void apply(FloatArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1302        virtual void apply(Vec2Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1303        virtual void apply(Vec3Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1304        virtual void apply(Vec4Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1305        virtual void apply(DoubleArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1306        virtual void apply(Vec2dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1307        virtual void apply(Vec3dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1308        virtual void apply(Vec4dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1309
1310
1311        inline void applyArray(Drawable::AttributeType type,Array* array)
1312        {
1313            if (array)
1314            {
1315                _type = type;
1316                array->accept(*this);
1317            }
1318        }
1319
1320    protected:
1321
1322        AttributeFunctorArrayVisitor& operator = (const AttributeFunctorArrayVisitor&) { return *this; }
1323        Drawable::AttributeFunctor&   _af;
1324        Drawable::AttributeType       _type;
1325};
1326
1327void Geometry::accept(AttributeFunctor& af)
1328{
1329    AttributeFunctorArrayVisitor afav(af);
1330
1331    if (_vertexData.array.valid())
1332    {
1333        afav.applyArray(VERTICES,_vertexData.array.get());
1334    }
1335    else if (_vertexAttribList.size()>0)
1336    {
1337        OSG_INFO<<"Geometry::accept(AttributeFunctor& af): Using vertex attribute instead"<<std::endl;
1338        afav.applyArray(VERTICES,_vertexAttribList[0].array.get());
1339    }
1340
1341    afav.applyArray(NORMALS,_normalData.array.get());
1342    afav.applyArray(COLORS,_colorData.array.get());
1343    afav.applyArray(SECONDARY_COLORS,_secondaryColorData.array.get());
1344    afav.applyArray(FOG_COORDS,_fogCoordData.array.get());
1345
1346    for(unsigned unit=0;unit<_texCoordList.size();++unit)
1347    {
1348        afav.applyArray((AttributeType)(TEXTURE_COORDS_0+unit),_texCoordList[unit].array.get());
1349    }
1350
1351    for(unsigned int index=0; index<_vertexAttribList.size(); ++index)
1352    {
1353        afav.applyArray(index,_vertexAttribList[index].array.get());
1354    }
1355}
1356
1357class ConstAttributeFunctorArrayVisitor : public ConstArrayVisitor
1358{
1359    public:
1360
1361        ConstAttributeFunctorArrayVisitor(Drawable::ConstAttributeFunctor& af):
1362            _af(af),
1363            _type(0) {}
1364
1365        virtual ~ConstAttributeFunctorArrayVisitor() {}
1366
1367        virtual void apply(const ByteArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1368        virtual void apply(const ShortArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1369        virtual void apply(const IntArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1370        virtual void apply(const UByteArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1371        virtual void apply(const UShortArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1372        virtual void apply(const UIntArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1373        virtual void apply(const Vec4ubArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1374        virtual void apply(const FloatArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1375        virtual void apply(const Vec2Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1376        virtual void apply(const Vec3Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1377        virtual void apply(const Vec4Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1378        virtual void apply(const DoubleArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1379        virtual void apply(const Vec2dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1380        virtual void apply(const Vec3dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1381        virtual void apply(const Vec4dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1382
1383
1384        inline void applyArray(Drawable::AttributeType type,const Array* array)
1385        {
1386            if (array)
1387            {
1388                _type = type;
1389                array->accept(*this);
1390            }
1391        }
1392
1393protected:
1394
1395        ConstAttributeFunctorArrayVisitor& operator = (const ConstAttributeFunctorArrayVisitor&) { return *this; }
1396
1397        Drawable::ConstAttributeFunctor&    _af;
1398        Drawable::AttributeType             _type;
1399};
1400
1401void Geometry::accept(ConstAttributeFunctor& af) const
1402{
1403    ConstAttributeFunctorArrayVisitor afav(af);
1404
1405    if (_vertexData.array.valid())
1406    {
1407        afav.applyArray(VERTICES,_vertexData.array.get());
1408    }
1409    else if (_vertexAttribList.size()>0)
1410    {
1411        OSG_INFO<<"Geometry::accept(ConstAttributeFunctor& af): Using vertex attribute instead"<<std::endl;
1412        afav.applyArray(VERTICES,_vertexAttribList[0].array.get());
1413    }
1414
1415    afav.applyArray(NORMALS,_normalData.array.get());
1416    afav.applyArray(COLORS,_colorData.array.get());
1417    afav.applyArray(SECONDARY_COLORS,_secondaryColorData.array.get());
1418    afav.applyArray(FOG_COORDS,_fogCoordData.array.get());
1419
1420    for(unsigned unit=0;unit<_texCoordList.size();++unit)
1421    {
1422        afav.applyArray((AttributeType)(TEXTURE_COORDS_0+unit),_texCoordList[unit].array.get());
1423    }
1424
1425    for(unsigned int index=0; index<_vertexAttribList.size(); ++index)
1426    {
1427        afav.applyArray(index,_vertexAttribList[index].array.get());
1428    }
1429}
1430
1431void Geometry::accept(PrimitiveFunctor& functor) const
1432{
1433    const osg::Array* vertices = _vertexData.array.get();
1434    const osg::IndexArray* indices = _vertexData.indices.get();
1435
1436    if (!vertices && _vertexAttribList.size()>0)
1437    {
1438        OSG_INFO<<"Using vertex attribute instead"<<std::endl;
1439        vertices = _vertexAttribList[0].array.get();
1440        indices = _vertexAttribList[0].indices.get();
1441    }
1442
1443    if (!vertices || vertices->getNumElements()==0) return;
1444
1445    if (!indices)
1446    {
1447        switch(vertices->getType())
1448        {
1449        case(Array::Vec2ArrayType):
1450            functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec2*>(vertices->getDataPointer()));
1451            break;
1452        case(Array::Vec3ArrayType):
1453            functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec3*>(vertices->getDataPointer()));
1454            break;
1455        case(Array::Vec4ArrayType):
1456            functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec4*>(vertices->getDataPointer()));
1457            break;
1458        case(Array::Vec2dArrayType):
1459            functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec2d*>(vertices->getDataPointer()));
1460            break;
1461        case(Array::Vec3dArrayType):
1462            functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec3d*>(vertices->getDataPointer()));
1463            break;
1464        case(Array::Vec4dArrayType):
1465            functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec4d*>(vertices->getDataPointer()));
1466            break;
1467        default:
1468            OSG_WARN<<"Warning: Geometry::accept(PrimitiveFunctor&) cannot handle Vertex Array type"<<vertices->getType()<<std::endl;
1469            return;
1470        }
1471
1472        for(PrimitiveSetList::const_iterator itr=_primitives.begin();
1473            itr!=_primitives.end();
1474            ++itr)
1475        {
1476            (*itr)->accept(functor);
1477        }
1478    }
1479    else
1480    {
1481        const Vec2* vec2Array = 0;
1482        const Vec3* vec3Array = 0;
1483        const Vec4* vec4Array = 0;
1484        const Vec2d* vec2dArray = 0;
1485        const Vec3d* vec3dArray = 0;
1486        const Vec4d* vec4dArray = 0;
1487        Array::Type type = vertices->getType();
1488        switch(type)
1489        {
1490        case(Array::Vec2ArrayType):
1491            vec2Array = static_cast<const Vec2*>(vertices->getDataPointer());
1492            break;
1493        case(Array::Vec3ArrayType):
1494            vec3Array = static_cast<const Vec3*>(vertices->getDataPointer());
1495            break;
1496        case(Array::Vec4ArrayType):
1497            vec4Array = static_cast<const Vec4*>(vertices->getDataPointer());
1498            break;
1499        case(Array::Vec2dArrayType):
1500            vec2dArray = static_cast<const Vec2d*>(vertices->getDataPointer());
1501            break;
1502        case(Array::Vec3dArrayType):
1503            vec3dArray = static_cast<const Vec3d*>(vertices->getDataPointer());
1504            break;
1505        case(Array::Vec4dArrayType):
1506            vec4dArray = static_cast<const Vec4d*>(vertices->getDataPointer());
1507            break;
1508        default:
1509            OSG_WARN<<"Warning: Geometry::accept(PrimitiveFunctor&) cannot handle Vertex Array type"<<vertices->getType()<<std::endl;
1510            return;
1511        }
1512
1513        for(PrimitiveSetList::const_iterator itr=_primitives.begin();
1514            itr!=_primitives.end();
1515            ++itr)
1516        {
1517            const PrimitiveSet* primitiveset = itr->get();
1518            GLenum mode=primitiveset->getMode();
1519            switch(primitiveset->getType())
1520            {
1521                case(PrimitiveSet::DrawArraysPrimitiveType):
1522                {
1523                    const DrawArrays* drawArray = static_cast<const DrawArrays*>(primitiveset);
1524                    functor.begin(mode);
1525
1526                    unsigned int indexEnd = drawArray->getFirst()+drawArray->getCount();
1527                    for(unsigned int vindex=drawArray->getFirst();
1528                        vindex<indexEnd;
1529                        ++vindex)
1530                    {
1531                        switch(type)
1532                        {
1533                        case(Array::Vec2ArrayType):
1534                            functor.vertex(vec2Array[_vertexData.indices->index(vindex)]);
1535                            break;
1536                        case(Array::Vec3ArrayType):
1537                            functor.vertex(vec3Array[_vertexData.indices->index(vindex)]);
1538                            break;
1539                        case(Array::Vec4ArrayType):
1540                            functor.vertex(vec4Array[_vertexData.indices->index(vindex)]);
1541                            break;
1542                        case(Array::Vec2dArrayType):
1543                            functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]);
1544                            break;
1545                        case(Array::Vec3dArrayType):
1546                            functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]);
1547                            break;
1548                        case(Array::Vec4dArrayType):
1549                            functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]);
1550                            break;
1551                        default:
1552                            break;
1553                        }
1554
1555                    }
1556
1557                    functor.end();
1558                    break;
1559                }
1560                case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
1561                {
1562
1563                    const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
1564                    unsigned int vindex=drawArrayLengths->getFirst();
1565                    for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
1566                        primItr!=drawArrayLengths->end();
1567                        ++primItr)
1568                    {
1569
1570                        functor.begin(mode);
1571
1572                        for(GLsizei primCount=0;primCount<*primItr;++primCount)
1573                        {
1574                            switch(type)
1575                            {
1576                            case(Array::Vec2ArrayType):
1577                                functor.vertex(vec2Array[_vertexData.indices->index(vindex)]);
1578                                break;
1579                            case(Array::Vec3ArrayType):
1580                                functor.vertex(vec3Array[_vertexData.indices->index(vindex)]);
1581                                break;
1582                            case(Array::Vec4ArrayType):
1583                                functor.vertex(vec4Array[_vertexData.indices->index(vindex)]);
1584                                break;
1585                            case(Array::Vec2dArrayType):
1586                                functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]);
1587                                break;
1588                            case(Array::Vec3dArrayType):
1589                                functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]);
1590                                break;
1591                            case(Array::Vec4dArrayType):
1592                                functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]);
1593                                break;
1594                            default:
1595                                break;
1596                            }
1597                            ++vindex;
1598                        }
1599
1600                        functor.end();
1601
1602                    }
1603                    break;
1604                }
1605                case(PrimitiveSet::DrawElementsUBytePrimitiveType):
1606                {
1607                    const DrawElementsUByte* drawElements = static_cast<const DrawElementsUByte*>(primitiveset);
1608                    functor.begin(mode);
1609
1610                    unsigned int primCount=0;
1611                    for(DrawElementsUByte::const_iterator primItr=drawElements->begin();
1612                        primItr!=drawElements->end();
1613                        ++primCount,++primItr)
1614                    {
1615                        unsigned int vindex=*primItr;
1616                        switch(type)
1617                        {
1618                        case(Array::Vec2ArrayType):
1619                            functor.vertex(vec2Array[_vertexData.indices->index(vindex)]);
1620                            break;
1621                        case(Array::Vec3ArrayType):
1622                            functor.vertex(vec3Array[_vertexData.indices->index(vindex)]);
1623                            break;
1624                        case(Array::Vec4ArrayType):
1625                            functor.vertex(vec4Array[_vertexData.indices->index(vindex)]);
1626                            break;
1627                        case(Array::Vec2dArrayType):
1628                            functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]);
1629                            break;
1630                        case(Array::Vec3dArrayType):
1631                            functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]);
1632                            break;
1633                        case(Array::Vec4dArrayType):
1634                            functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]);
1635                            break;
1636                        default:
1637                            break;
1638                        }
1639                    }
1640
1641                    functor.end();
1642                    break;
1643                }
1644                case(PrimitiveSet::DrawElementsUShortPrimitiveType):
1645                {
1646                    const DrawElementsUShort* drawElements = static_cast<const DrawElementsUShort*>(primitiveset);
1647                    functor.begin(mode);
1648
1649                    for(DrawElementsUShort::const_iterator primItr=drawElements->begin();
1650                        primItr!=drawElements->end();
1651                        ++primItr)
1652                    {
1653                        unsigned int vindex=*primItr;
1654                        switch(type)
1655                        {
1656                        case(Array::Vec2ArrayType):
1657                            functor.vertex(vec2Array[_vertexData.indices->index(vindex)]);
1658                            break;
1659                        case(Array::Vec3ArrayType):
1660                            functor.vertex(vec3Array[_vertexData.indices->index(vindex)]);
1661                            break;
1662                        case(Array::Vec4ArrayType):
1663                            functor.vertex(vec4Array[_vertexData.indices->index(vindex)]);
1664                            break;
1665                        case(Array::Vec2dArrayType):
1666                            functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]);
1667                            break;
1668                        case(Array::Vec3dArrayType):
1669                            functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]);
1670                            break;
1671                        case(Array::Vec4dArrayType):
1672                            functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]);
1673                            break;
1674                        default:
1675                            break;
1676                        }
1677                    }
1678
1679                    functor.end();
1680                    break;
1681                }
1682                case(PrimitiveSet::DrawElementsUIntPrimitiveType):
1683                {
1684                    const DrawElementsUInt* drawElements = static_cast<const DrawElementsUInt*>(primitiveset);
1685                    functor.begin(mode);
1686
1687                    for(DrawElementsUInt::const_iterator primItr=drawElements->begin();
1688                        primItr!=drawElements->end();
1689                        ++primItr)
1690                    {
1691                        unsigned int vindex=*primItr;
1692                        switch(type)
1693                        {
1694                        case(Array::Vec2ArrayType):
1695                            functor.vertex(vec2Array[_vertexData.indices->index(vindex)]);
1696                            break;
1697                        case(Array::Vec3ArrayType):
1698                            functor.vertex(vec3Array[_vertexData.indices->index(vindex)]);
1699                            break;
1700                        case(Array::Vec4ArrayType):
1701                            functor.vertex(vec4Array[_vertexData.indices->index(vindex)]);
1702                            break;
1703                        case(Array::Vec2dArrayType):
1704                            functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]);
1705                            break;
1706                        case(Array::Vec3dArrayType):
1707                            functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]);
1708                            break;
1709                        case(Array::Vec4dArrayType):
1710                            functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]);
1711                            break;
1712                        default:
1713                            break;
1714                        }
1715                    }
1716
1717                    functor.end();
1718                    break;
1719                }
1720                default:
1721                {
1722                    break;
1723                }
1724            }
1725        }
1726    }
1727    return;
1728}
1729
1730void Geometry::accept(PrimitiveIndexFunctor& functor) const
1731{
1732    const osg::Array* vertices = _vertexData.array.get();
1733    const osg::IndexArray* indices = _vertexData.indices.get();
1734
1735    if (!vertices && _vertexAttribList.size()>0)
1736    {
1737        OSG_INFO<<"Geometry::accept(PrimitiveIndexFunctor& functor): Using vertex attribute instead"<<std::endl;
1738        vertices = _vertexAttribList[0].array.get();
1739        indices = _vertexAttribList[0].indices.get();
1740    }
1741
1742    if (!vertices || vertices->getNumElements()==0) return;
1743
1744    switch(vertices->getType())
1745    {
1746    case(Array::Vec2ArrayType):
1747        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec2*>(vertices->getDataPointer()));
1748        break;
1749    case(Array::Vec3ArrayType):
1750        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec3*>(vertices->getDataPointer()));
1751        break;
1752    case(Array::Vec4ArrayType):
1753        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec4*>(vertices->getDataPointer()));
1754        break;
1755    case(Array::Vec2dArrayType):
1756        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec2d*>(vertices->getDataPointer()));
1757        break;
1758    case(Array::Vec3dArrayType):
1759        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec3d*>(vertices->getDataPointer()));
1760        break;
1761    case(Array::Vec4dArrayType):
1762        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec4d*>(vertices->getDataPointer()));
1763        break;
1764    default:
1765        OSG_WARN<<"Warning: Geometry::accept(PrimitiveIndexFunctor&) cannot handle Vertex Array type"<<vertices->getType()<<std::endl;
1766        return;
1767    }
1768
1769    if (!indices)
1770    {
1771        for(PrimitiveSetList::const_iterator itr=_primitives.begin();
1772            itr!=_primitives.end();
1773            ++itr)
1774        {
1775            (*itr)->accept(functor);
1776        }
1777    }
1778    else
1779    {
1780        for(PrimitiveSetList::const_iterator itr=_primitives.begin();
1781            itr!=_primitives.end();
1782            ++itr)
1783        {
1784            const PrimitiveSet* primitiveset = itr->get();
1785            GLenum mode=primitiveset->getMode();
1786            switch(primitiveset->getType())
1787            {
1788                case(PrimitiveSet::DrawArraysPrimitiveType):
1789                {
1790                    const DrawArrays* drawArray = static_cast<const DrawArrays*>(primitiveset);
1791                    functor.begin(mode);
1792
1793                    unsigned int indexEnd = drawArray->getFirst()+drawArray->getCount();
1794                    for(unsigned int vindex=drawArray->getFirst();
1795                        vindex<indexEnd;
1796                        ++vindex)
1797                    {
1798                        functor.vertex(indices->index(vindex));
1799                    }
1800
1801                    functor.end();
1802                    break;
1803                }
1804                case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
1805                {
1806
1807                    const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
1808                    unsigned int vindex=drawArrayLengths->getFirst();
1809                    for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
1810                        primItr!=drawArrayLengths->end();
1811                        ++primItr)
1812                    {
1813
1814                        functor.begin(mode);
1815
1816                        for(GLsizei primCount=0;primCount<*primItr;++primCount)
1817                        {
1818                            functor.vertex(indices->index(vindex));
1819                            ++vindex;
1820                        }
1821
1822                        functor.end();
1823
1824                    }
1825                    break;
1826                }
1827                case(PrimitiveSet::DrawElementsUBytePrimitiveType):
1828                {
1829                    const DrawElementsUByte* drawElements = static_cast<const DrawElementsUByte*>(primitiveset);
1830                    functor.begin(mode);
1831
1832                    unsigned int primCount=0;
1833                    for(DrawElementsUByte::const_iterator primItr=drawElements->begin();
1834                        primItr!=drawElements->end();
1835                        ++primCount,++primItr)
1836                    {
1837                        unsigned int vindex=*primItr;
1838                        functor.vertex(indices->index(vindex));
1839                    }
1840
1841                    functor.end();
1842                    break;
1843                }
1844                case(PrimitiveSet::DrawElementsUShortPrimitiveType):
1845                {
1846                    const DrawElementsUShort* drawElements = static_cast<const DrawElementsUShort*>(primitiveset);
1847                    functor.begin(mode);
1848
1849                    for(DrawElementsUShort::const_iterator primItr=drawElements->begin();
1850                        primItr!=drawElements->end();
1851                        ++primItr)
1852                    {
1853                        unsigned int vindex=*primItr;
1854                        functor.vertex(indices->index(vindex));
1855                    }
1856
1857                    functor.end();
1858                    break;
1859                }
1860                case(PrimitiveSet::DrawElementsUIntPrimitiveType):
1861                {
1862                    const DrawElementsUInt* drawElements = static_cast<const DrawElementsUInt*>(primitiveset);
1863                    functor.begin(mode);
1864
1865                    for(DrawElementsUInt::const_iterator primItr=drawElements->begin();
1866                        primItr!=drawElements->end();
1867                        ++primItr)
1868                    {
1869                        unsigned int vindex=*primItr;
1870                        functor.vertex(indices->index(vindex));
1871                    }
1872
1873                    functor.end();
1874                    break;
1875                }
1876                default:
1877                {
1878                    break;
1879                }
1880            }
1881        }
1882    }
1883    return;
1884}
1885
1886unsigned int _computeNumberOfPrimitives(const osg::Geometry& geom)
1887{
1888
1889    unsigned int totalNumberOfPrimitives = 0;
1890
1891    for(Geometry::PrimitiveSetList::const_iterator itr=geom.getPrimitiveSetList().begin();
1892        itr!=geom.getPrimitiveSetList().end();
1893        ++itr)
1894    {
1895        const PrimitiveSet* primitiveset = itr->get();
1896        GLenum mode=primitiveset->getMode();
1897
1898        unsigned int primLength;
1899        switch(mode)
1900        {
1901            case(GL_POINTS):    primLength=1; OSG_INFO<<"prim=GL_POINTS"<<std::endl; break;
1902            case(GL_LINES):     primLength=2; OSG_INFO<<"prim=GL_LINES"<<std::endl; break;
1903            case(GL_TRIANGLES): primLength=3; OSG_INFO<<"prim=GL_TRIANGLES"<<std::endl; break;
1904            case(GL_QUADS):     primLength=4; OSG_INFO<<"prim=GL_QUADS"<<std::endl; break;
1905            default:            primLength=0; OSG_INFO<<"prim="<<std::hex<<mode<<std::dec<<std::endl; break; // compute later when =0.
1906        }
1907
1908        // draw primitives by the more flexible "slow" path,
1909        // sending OpenGL Begin/glVertex.../End().
1910        switch(primitiveset->getType())
1911        {
1912            case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
1913            {
1914
1915                const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
1916                for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
1917                    primItr!=drawArrayLengths->end();
1918                    ++primItr)
1919                {
1920                    if (primLength==0) totalNumberOfPrimitives += 1;
1921                    else totalNumberOfPrimitives += *primItr/primLength;
1922                }
1923                break;
1924            }
1925            default:
1926            {
1927                if (primLength==0) { totalNumberOfPrimitives += 1; OSG_INFO<<"   totalNumberOfPrimitives="<<totalNumberOfPrimitives<<std::endl;}
1928                else { totalNumberOfPrimitives += primitiveset->getNumIndices()/primLength; OSG_INFO<<"   primitiveset->getNumIndices()="<<primitiveset->getNumIndices()<<" totalNumberOfPrimitives="<<totalNumberOfPrimitives<<std::endl; }
1929
1930            }
1931        }
1932    }
1933
1934    return totalNumberOfPrimitives;
1935}
1936
1937template<class A>
1938bool _verifyBindings(const osg::Geometry& geom, const A& arrayData)
1939{
1940    unsigned int numElements = arrayData.indices.valid()?arrayData.indices->getNumElements():
1941                               arrayData.array.valid()?arrayData.array->getNumElements():0;
1942
1943    switch(arrayData.binding)
1944    {
1945        case(osg::Geometry::BIND_OFF):
1946            if (numElements>0) return false;
1947            break;
1948        case(osg::Geometry::BIND_OVERALL):
1949            if (numElements!=1) return false;
1950            break;
1951        case(osg::Geometry::BIND_PER_PRIMITIVE_SET):
1952            if (numElements!=geom.getPrimitiveSetList().size()) return false;
1953            break;
1954        case(osg::Geometry::BIND_PER_PRIMITIVE):
1955            if (numElements!=_computeNumberOfPrimitives(geom)) return false;
1956            break;
1957        case(osg::Geometry::BIND_PER_VERTEX):
1958        {
1959            unsigned int numVertices = geom.getVertexIndices()?geom.getVertexIndices()->getNumElements():
1960                                       geom.getVertexArray()?geom.getVertexArray()->getNumElements():0;
1961            if (numElements!=numVertices) return false;
1962            break;
1963        }
1964    }
1965    return true;
1966}
1967
1968template<class A>
1969void _computeCorrectBindingsAndArraySizes(std::ostream& out, const osg::Geometry& geom, A& arrayData, const char* arrayName)
1970{
1971    unsigned int numElements = arrayData.indices.valid()?arrayData.indices->getNumElements():
1972                               arrayData.array.valid()?arrayData.array->getNumElements():0;
1973
1974    // check to see if binding matches 0 elements required.
1975    if (numElements==0)
1976    {
1977        // correct binding if not correct.
1978        if (arrayData.binding!=osg::Geometry::BIND_OFF)
1979        {
1980            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() "<<std::endl
1981                   <<"         "<<arrayName<<" binding has been reset to BIND_OFF"<<std::endl;
1982            arrayData.binding=osg::Geometry::BIND_OFF;
1983        }
1984        return;
1985    }
1986
1987    // check to see if binding matches 1 elements required.
1988    if (numElements==1)
1989    {
1990        // correct binding if not correct.
1991        if (arrayData.binding!=osg::Geometry::BIND_OVERALL)
1992        {
1993            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() "<<std::endl
1994                   <<"         "<<arrayName<<" binding has been reset to BIND_OVERALL"<<std::endl;
1995            arrayData.binding=osg::Geometry::BIND_OVERALL;
1996        }
1997        return;
1998    }
1999
2000
2001    unsigned int numVertices = geom.getVertexIndices()?geom.getVertexIndices()->getNumElements():
2002                               geom.getVertexArray()?geom.getVertexArray()->getNumElements():0;
2003
2004    if ( numVertices==0 )
2005    {
2006        if (arrayData.binding!=osg::Geometry::BIND_OFF)
2007        {
2008            arrayData.array = 0;
2009            arrayData.indices = 0;
2010            arrayData.binding = osg::Geometry::BIND_OFF;
2011            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() vertex array is empty but "<<std::endl
2012                <<"         vertex array is empty but"<<arrayName<<" is set"<<std::endl
2013                <<"         reseting "<<arrayName<< " binding to BIND_OFF and array & indices to 0."<<std::endl;
2014        }
2015    }
2016
2017    if (numElements==numVertices)
2018    {
2019        // correct the binding to per vertex.
2020        if (arrayData.binding!=osg::Geometry::BIND_PER_VERTEX)
2021        {
2022            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() "<<std::endl
2023                   <<"         "<<arrayName<<" binding has been reset to BIND_PER_VERTEX"<<std::endl;
2024            arrayData.binding = osg::Geometry::BIND_PER_VERTEX;
2025        }
2026        return;
2027    }
2028
2029
2030
2031    // check to see if binding might be per primitive set
2032    unsigned int numPrimitiveSets = geom.getPrimitiveSetList().size();
2033
2034    if (numElements==numPrimitiveSets)
2035    {
2036        if (arrayData.binding != osg::Geometry::BIND_PER_PRIMITIVE_SET)
2037        {
2038            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() "<<std::endl
2039                   <<"         "<<arrayName<<" binding has been reset to BIND_PER_PRIMITIVE_SET"<<std::endl;
2040            arrayData.binding = osg::Geometry::BIND_PER_PRIMITIVE_SET;
2041        }
2042        return;
2043    }
2044
2045    // check to see if binding might be per primitive
2046    unsigned int numPrimitives = _computeNumberOfPrimitives(geom);
2047    if (numElements==numPrimitives)
2048    {
2049        if (arrayData.binding != osg::Geometry::BIND_PER_PRIMITIVE)
2050        {
2051            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() "<<std::endl
2052                   <<"         "<<arrayName<<" binding has been reset to BIND_PER_PRIMITIVE"<<std::endl;
2053            arrayData.binding = osg::Geometry::BIND_PER_PRIMITIVE;
2054        }
2055        return;
2056    }
2057
2058    if (numElements>numVertices)
2059    {
2060        arrayData.binding = osg::Geometry::BIND_PER_VERTEX;
2061        return;
2062    }
2063    if (numElements>numPrimitives)
2064    {
2065        arrayData.binding = osg::Geometry::BIND_PER_PRIMITIVE;
2066        return;
2067    }
2068    if (numElements>numPrimitiveSets)
2069    {
2070        arrayData.binding = osg::Geometry::BIND_PER_PRIMITIVE_SET;
2071        return;
2072    }
2073    if (numElements>=1)
2074    {
2075        arrayData.binding = osg::Geometry::BIND_OVERALL;
2076        return;
2077    }
2078    arrayData.binding = osg::Geometry::BIND_OFF;
2079
2080}
2081
2082bool Geometry::verifyBindings(const ArrayData& arrayData) const
2083{
2084    return _verifyBindings(*this,arrayData);
2085}
2086
2087bool Geometry::verifyBindings(const Vec3ArrayData& arrayData) const
2088{
2089    return _verifyBindings(*this,arrayData);
2090}
2091
2092void Geometry::computeCorrectBindingsAndArraySizes(ArrayData& arrayData, const char* arrayName)
2093{
2094    _computeCorrectBindingsAndArraySizes(osg::notify(osg::INFO),*this,arrayData,arrayName);
2095}
2096
2097void Geometry::computeCorrectBindingsAndArraySizes(Vec3ArrayData& arrayData, const char* arrayName)
2098{
2099    _computeCorrectBindingsAndArraySizes(osg::notify(osg::INFO),*this,arrayData,arrayName);
2100}
2101
2102bool Geometry::verifyBindings() const
2103{
2104    if (!verifyBindings(_normalData)) return false;
2105    if (!verifyBindings(_colorData)) return false;
2106    if (!verifyBindings(_secondaryColorData)) return false;
2107    if (!verifyBindings(_fogCoordData)) return false;
2108
2109    for(ArrayDataList::const_iterator titr=_texCoordList.begin();
2110        titr!=_texCoordList.end();
2111        ++titr)
2112    {
2113        if (!verifyBindings(*titr)) return false;
2114    }
2115
2116    for(ArrayDataList::const_iterator vitr=_vertexAttribList.begin();
2117        vitr!=_vertexAttribList.end();
2118        ++vitr)
2119    {
2120        if (!verifyBindings(*vitr)) return false;
2121    }
2122
2123    return true;
2124}
2125
2126void Geometry::computeCorrectBindingsAndArraySizes()
2127{
2128    // if (verifyBindings()) return;
2129
2130    computeCorrectBindingsAndArraySizes(_normalData,"_normalData");
2131    computeCorrectBindingsAndArraySizes(_colorData,"_colorData");
2132    computeCorrectBindingsAndArraySizes(_secondaryColorData,"_secondaryColorData");
2133    computeCorrectBindingsAndArraySizes(_fogCoordData,"_fogCoordData");
2134
2135    for(ArrayDataList::iterator titr=_texCoordList.begin();
2136        titr!=_texCoordList.end();
2137        ++titr)
2138    {
2139        computeCorrectBindingsAndArraySizes(*titr,"_texCoordList[]");
2140    }
2141
2142    for(ArrayDataList::iterator vitr=_vertexAttribList.begin();
2143        vitr!=_vertexAttribList.end();
2144        ++vitr)
2145    {
2146        computeCorrectBindingsAndArraySizes(*vitr,"_vertAttribList[]");
2147    }
2148}
2149
2150class ExpandIndexedArray : public osg::ConstArrayVisitor
2151{
2152    public:
2153        ExpandIndexedArray(const osg::IndexArray& indices,Array* targetArray):
2154            _indices(indices),
2155            _targetArray(targetArray) {}
2156
2157        virtual ~ExpandIndexedArray() {}
2158
2159        // Create when both of the arrays are predefined templated classes. We
2160        // can do some optimizations in this case that aren't possible in the general
2161        // case.
2162        template <class T,class I>
2163        T* create_inline(const T& array,const I& indices)
2164        {
2165            T* newArray = 0;
2166
2167            // if source array type and target array type are equal but arrays arn't equal
2168            if (_targetArray && _targetArray->getType()==array.getType() && _targetArray!=(osg::Array*)(&array))
2169            {
2170                // reuse exisiting target array
2171                newArray = static_cast<T*>(_targetArray);
2172                if (newArray->size()!=indices.size())
2173                {
2174                    // make sure its the right size
2175                    newArray->resize(indices.size());
2176                }
2177            }
2178            else
2179            {
2180                //  else create a new array.
2181                newArray = new T(indices.size());
2182            }
2183
2184            for(unsigned int i=0;i<indices.size();++i)
2185            {
2186                (*newArray)[i]= array[indices[i]];
2187            }
2188
2189            return newArray;
2190        }
2191
2192        // Create when one of the arrays isn't one of the predefined templated classes. The
2193        // template parameter is the type of the array that will get created. This is  always
2194        // one of the predefined classes. We could call clone to get one of the same type as
2195        // the input array, but the interface of the osg::Array class doesn't include a way
2196        // to set an element.
2197        template <class T>
2198        osg::Array* create_noinline(const osg::Array& array, const osg::IndexArray& indices)
2199        {
2200            T* newArray = 0;
2201            typedef typename T::ElementDataType EDT;
2202
2203            unsigned int num_indices = indices.getNumElements();
2204            newArray = new T(num_indices);
2205
2206            const EDT* src = static_cast<const EDT*>(array.getDataPointer());
2207
2208            for(unsigned int i=0;i<num_indices;++i)
2209            {
2210                (*newArray)[i]= src[indices.index(i)];
2211            }
2212
2213            return newArray;
2214        }
2215
2216        osg::Array* create_noinline(const osg::Array& array, const osg::IndexArray& indices)
2217        {
2218            switch (array.getType())
2219            {
2220                case(osg::Array::ByteArrayType):   return create_noinline<osg::ByteArray>(array,indices);
2221                case(osg::Array::ShortArrayType):  return create_noinline<osg::ShortArray>(array,indices);
2222                case(osg::Array::IntArrayType):    return create_noinline<osg::IntArray>(array,indices);
2223                case(osg::Array::UByteArrayType):  return create_noinline<osg::UByteArray>(array,indices);
2224                case(osg::Array::UShortArrayType): return create_noinline<osg::UShortArray>(array,indices);
2225                case(osg::Array::UIntArrayType):   return create_noinline<osg::UIntArray>(array,indices);
2226                case(osg::Array::Vec4ubArrayType): return create_noinline<osg::Vec4ubArray>(array,indices);
2227                case(osg::Array::FloatArrayType):  return create_noinline<osg::FloatArray>(array,indices);
2228                case(osg::Array::Vec2ArrayType):   return create_noinline<osg::Vec2Array>(array,indices);
2229                case(osg::Array::Vec3ArrayType):   return create_noinline<osg::Vec3Array>(array,indices);
2230                case(osg::Array::Vec4ArrayType):   return create_noinline<osg::Vec4Array>(array,indices);
2231                case(osg::Array::Vec2dArrayType):   return create_noinline<osg::Vec2dArray>(array,indices);
2232                case(osg::Array::Vec3dArrayType):   return create_noinline<osg::Vec3dArray>(array,indices);
2233                case(osg::Array::Vec4dArrayType):   return create_noinline<osg::Vec4dArray>(array,indices);
2234                default:
2235                    return NULL;
2236            }
2237        }
2238
2239        template <class TA, class TI>
2240        osg::Array* create(const TA& array, const osg::IndexArray& indices)
2241        {
2242            // We know that indices.getType returned the same thing as TI, but
2243            // we need to determine whether it is really an instance of TI, or
2244            // perhaps another subclass of osg::Array that contains the same
2245            // type of data.
2246            const TI* ba(dynamic_cast<const TI*>(&indices));
2247            if (ba != NULL) {
2248                return create_inline(array,*ba);
2249            }
2250            else {
2251                return create_noinline(array, _indices);
2252            }
2253        }
2254
2255        template <class T>
2256        osg::Array* create(const T& array)
2257        {
2258            switch(_indices.getType())
2259            {
2260            case(osg::Array::ByteArrayType):   return create<T, osg::ByteArray>(array, _indices);
2261            case(osg::Array::ShortArrayType):  return create<T, osg::ShortArray>(array, _indices);
2262            case(osg::Array::IntArrayType):    return create<T, osg::IntArray>(array, _indices);
2263            case(osg::Array::UByteArrayType):  return create<T, osg::UByteArray>(array, _indices);
2264            case(osg::Array::UShortArrayType): return create<T, osg::UShortArray>(array, _indices);
2265            case(osg::Array::UIntArrayType):   return create<T, osg::UIntArray>(array, _indices);
2266            default:                           return create_noinline(array, _indices);
2267            }
2268
2269        }
2270
2271        // applys for the predefined classes go through 1-arg create to do indexing
2272        virtual void apply(const osg::ByteArray& array) { _targetArray = create(array); }
2273        virtual void apply(const osg::ShortArray& array) { _targetArray = create(array); }
2274        virtual void apply(const osg::IntArray& array) { _targetArray = create(array); }
2275        virtual void apply(const osg::UByteArray& array) { _targetArray = create(array); }
2276        virtual void apply(const osg::UShortArray& array) { _targetArray = create(array); }
2277        virtual void apply(const osg::UIntArray& array) { _targetArray = create(array); }
2278        virtual void apply(const osg::Vec4ubArray& array) { _targetArray = create(array); }
2279        virtual void apply(const osg::FloatArray& array) { _targetArray = create(array); }
2280        virtual void apply(const osg::Vec2Array& array) { _targetArray = create(array); }
2281        virtual void apply(const osg::Vec3Array& array) { _targetArray = create(array); }
2282        virtual void apply(const osg::Vec4Array& array) { _targetArray = create(array); }
2283
2284        // other subclasses of osg::Array end up here
2285        virtual void apply(const osg::Array& array) { _targetArray = create_noinline(array, _indices); }
2286
2287        const osg::IndexArray& _indices;
2288        osg::Array* _targetArray;
2289
2290    protected:
2291
2292        ExpandIndexedArray& operator = (const ExpandIndexedArray&) { return *this; }
2293
2294};
2295
2296bool Geometry::suitableForOptimization() const
2297{
2298    bool hasIndices = false;
2299
2300    if (getVertexIndices()) hasIndices = true;
2301
2302    if (getNormalIndices()) hasIndices = true;
2303
2304    if (getColorIndices()) hasIndices = true;
2305
2306    if (getSecondaryColorIndices()) hasIndices = true;
2307
2308    if (getFogCoordIndices()) hasIndices = true;
2309
2310    for(unsigned int ti=0;ti<getNumTexCoordArrays();++ti)
2311    {
2312        if (getTexCoordIndices(ti)) hasIndices = true;
2313    }
2314
2315    for(unsigned int vi=0;vi<getNumVertexAttribArrays();++vi)
2316    {
2317        if (getVertexAttribIndices(vi)) hasIndices = true;
2318    }
2319
2320    return hasIndices;
2321}
2322
2323void Geometry::copyToAndOptimize(Geometry& target)
2324{
2325    bool copyToSelf = (this==&target);
2326
2327    // copy over primitive sets.
2328    if (!copyToSelf) target.getPrimitiveSetList() = getPrimitiveSetList();
2329
2330    // copy over attribute arrays.
2331    if (getVertexIndices() && getVertexArray())
2332    {
2333        ExpandIndexedArray eia(*(getVertexIndices()),target.getVertexArray());
2334        getVertexArray()->accept(eia);
2335
2336        target.setVertexArray(eia._targetArray);
2337        target.setVertexIndices(0);
2338    }
2339    else if (getVertexArray())
2340    {
2341        if (!copyToSelf) target.setVertexArray(getVertexArray());
2342    }
2343
2344    target.setNormalBinding(getNormalBinding());
2345    if (getNormalIndices() && getNormalArray())
2346    {
2347        ExpandIndexedArray eia(*(getNormalIndices()),target.getNormalArray());
2348        getNormalArray()->accept(eia);
2349
2350        target.setNormalArray(dynamic_cast<osg::Vec3Array*>(eia._targetArray));
2351        target.setNormalIndices(0);
2352    }
2353    else if (getNormalArray())
2354    {
2355        if (!copyToSelf) target.setNormalArray(getNormalArray());
2356    }
2357
2358    target.setColorBinding(getColorBinding());
2359    if (getColorIndices() && getColorArray())
2360    {
2361        ExpandIndexedArray eia(*(getColorIndices()),target.getColorArray());
2362        getColorArray()->accept(eia);
2363
2364        target.setColorArray(eia._targetArray);
2365        target.setColorIndices(0);
2366    }
2367    else if (getColorArray())
2368    {
2369        if (!copyToSelf) target.setColorArray(getColorArray());
2370    }
2371
2372    target.setSecondaryColorBinding(getSecondaryColorBinding());
2373    if (getSecondaryColorIndices() && getSecondaryColorArray())
2374    {
2375        ExpandIndexedArray eia(*(getSecondaryColorIndices()),target.getSecondaryColorArray());
2376        getSecondaryColorArray()->accept(eia);
2377
2378        target.setSecondaryColorArray(eia._targetArray);
2379        target.setSecondaryColorIndices(0);
2380    }
2381    else if (getSecondaryColorArray())
2382    {
2383        if (!copyToSelf) target.setSecondaryColorArray(getSecondaryColorArray());
2384    }
2385
2386    target.setFogCoordBinding(getFogCoordBinding());
2387    if (getFogCoordIndices() && getFogCoordArray())
2388    {
2389        ExpandIndexedArray eia(*(getFogCoordIndices()),target.getFogCoordArray());
2390        getFogCoordArray()->accept(eia);
2391
2392        target.setFogCoordArray(eia._targetArray);
2393        target.setFogCoordIndices(0);
2394    }
2395    else if (getFogCoordArray())
2396    {
2397        if (!copyToSelf) target.setFogCoordArray(getFogCoordArray());
2398    }
2399
2400    for(unsigned int ti=0;ti<getNumTexCoordArrays();++ti)
2401    {
2402        if (getTexCoordIndices(ti) && getTexCoordArray(ti))
2403        {
2404            ExpandIndexedArray eia(*(getTexCoordIndices(ti)),target.getTexCoordArray(ti));
2405
2406            getTexCoordArray(ti)->accept(eia);
2407
2408            target.setTexCoordArray(ti,eia._targetArray);
2409            target.setTexCoordIndices(ti,0);
2410        }
2411        else if (getTexCoordArray(ti))
2412        {
2413            if (!copyToSelf) target.setTexCoordArray(ti,getTexCoordArray(ti));
2414        }
2415    }
2416
2417    for(unsigned int vi=0;vi<_vertexAttribList.size();++vi)
2418    {
2419        ArrayData& arrayData = _vertexAttribList[vi];
2420        if (arrayData.indices.valid())
2421        {
2422            ExpandIndexedArray eia(*arrayData.indices,target.getVertexAttribArray(vi));
2423            arrayData.array->accept(eia);
2424            target.setVertexAttribData(vi,ArrayData(eia._targetArray, 0, arrayData.binding, arrayData.normalize));
2425        }
2426        else if (arrayData.array.valid())
2427        {
2428            if (!copyToSelf) target.setVertexAttribData(vi,arrayData);
2429        }
2430    }
2431}
2432
2433bool Geometry::containsSharedArrays() const
2434{
2435    unsigned int numSharedArrays = 0;
2436
2437    if (getVertexArray() && getVertexArray()->referenceCount()>1) ++numSharedArrays;
2438    if (getNormalArray() && getNormalArray()->referenceCount()>1) ++numSharedArrays;
2439    if (getColorArray() && getColorArray()->referenceCount()>1) ++numSharedArrays;
2440    if (getSecondaryColorArray() && getSecondaryColorArray()->referenceCount()>1) ++numSharedArrays;
2441    if (getFogCoordArray() && getFogCoordArray()->referenceCount()>1) ++numSharedArrays;
2442
2443    for(unsigned int ti=0;ti<getNumTexCoordArrays();++ti)
2444    {
2445        if (getTexCoordArray(ti) && getTexCoordArray(ti)->referenceCount()>1) ++numSharedArrays;
2446    }
2447
2448    for(unsigned int vi=0;vi<_vertexAttribList.size();++vi)
2449    {
2450        const ArrayData& arrayData = _vertexAttribList[vi];
2451        if (arrayData.array.valid() && arrayData.array->referenceCount()>1) ++numSharedArrays;
2452    }
2453    return numSharedArrays!=0;
2454}
2455
2456void Geometry::duplicateSharedArrays()
2457{
2458    #define DUPLICATE_IF_REQUIRED(A) \
2459        if (get##A() && get##A()->referenceCount()>1) \
2460        { \
2461            set##A(osg::clone(get##A(), osg::CopyOp::DEEP_COPY_ARRAYS)); \
2462        }
2463
2464    DUPLICATE_IF_REQUIRED(VertexArray)
2465    DUPLICATE_IF_REQUIRED(NormalArray)
2466    DUPLICATE_IF_REQUIRED(ColorArray)
2467    DUPLICATE_IF_REQUIRED(SecondaryColorArray)
2468    DUPLICATE_IF_REQUIRED(FogCoordArray)
2469
2470    for(unsigned int ti=0;ti<getNumTexCoordArrays();++ti)
2471    {
2472        if (getTexCoordArray(ti) && getTexCoordArray(ti)->referenceCount()>1)
2473        {
2474            setTexCoordArray(ti, osg::clone(getTexCoordArray(ti),osg::CopyOp::DEEP_COPY_ARRAYS));
2475        }
2476    }
2477
2478    for(unsigned int vi=0;vi<_vertexAttribList.size();++vi)
2479    {
2480        ArrayData& arrayData = _vertexAttribList[vi];
2481        if (arrayData.array.valid() && arrayData.array->referenceCount()>1)
2482        {
2483            arrayData.array = osg::clone(arrayData.array.get(), osg::CopyOp::DEEP_COPY_ARRAYS);
2484        }
2485    }
2486}
2487
2488void Geometry::computeInternalOptimizedGeometry()
2489{
2490    if (suitableForOptimization())
2491    {
2492        if (!_internalOptimizedGeometry) _internalOptimizedGeometry = new Geometry;
2493
2494        copyToAndOptimize(*_internalOptimizedGeometry);
2495    }
2496}
2497
2498class CheckArrayValidity
2499{
2500public:
2501    CheckArrayValidity(const osg::Geometry* geometry)
2502    {
2503        numPrimitiveSets = geometry->getNumPrimitiveSets();
2504        primitiveNum = 0;
2505        maxVertexNumber = 0;
2506
2507        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2508        //
2509        // draw the primitives themselves.
2510        //
2511        for(unsigned int primitiveSetNum=0; primitiveSetNum != numPrimitiveSets; ++primitiveSetNum)
2512        {
2513            const PrimitiveSet* primitiveset = geometry->getPrimitiveSet(primitiveSetNum);
2514
2515            GLenum mode=primitiveset->getMode();
2516
2517            unsigned int primLength;
2518            switch(mode)
2519            {
2520                case(GL_POINTS):    primLength=1; break;
2521                case(GL_LINES):     primLength=2; break;
2522                case(GL_TRIANGLES): primLength=3; break;
2523                case(GL_QUADS):     primLength=4; break;
2524                default:            primLength=0; break; // compute later when =0.
2525            }
2526
2527            // draw primitives by the more flexible "slow" path,
2528            // sending OpenGL glBegin/glVertex.../glEnd().
2529            switch(primitiveset->getType())
2530            {
2531                case(PrimitiveSet::DrawArraysPrimitiveType):
2532                {
2533                    if (primLength==0) primLength=primitiveset->getNumIndices();
2534
2535                    const DrawArrays* drawArray = static_cast<const DrawArrays*>(primitiveset);
2536
2537                    unsigned int primCount=0;
2538                    unsigned int indexEnd = drawArray->getFirst()+drawArray->getCount();
2539                    for(unsigned int vindex=drawArray->getFirst();
2540                        vindex<indexEnd;
2541                        ++vindex,++primCount)
2542                    {
2543                        if ((primCount%primLength)==0)
2544                        {
2545                            primitiveNum++;
2546                        }
2547                    }
2548                    if ((indexEnd-1) > maxVertexNumber) maxVertexNumber = (indexEnd-1);
2549                    break;
2550                }
2551                case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
2552                {
2553                    const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
2554                    unsigned int vindex=drawArrayLengths->getFirst();
2555                    for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
2556                        primItr!=drawArrayLengths->end();
2557                        ++primItr)
2558                    {
2559                        unsigned int localPrimLength;
2560                        if (primLength==0) localPrimLength=*primItr;
2561                        else localPrimLength=primLength;
2562
2563                        for(GLsizei primCount=0;
2564                            primCount<*primItr;
2565                            ++vindex,++primCount)
2566                        {
2567                            if ((primCount%localPrimLength)==0)
2568                            {
2569                                primitiveNum++;
2570                            }
2571                        }
2572
2573                    }
2574                    if ((vindex-1) > maxVertexNumber) maxVertexNumber = (vindex-1);
2575                    break;
2576                }
2577                case(PrimitiveSet::DrawElementsUBytePrimitiveType):
2578                {
2579                    if (primLength==0) primLength=primitiveset->getNumIndices();
2580
2581                    const DrawElementsUByte* drawElements = static_cast<const DrawElementsUByte*>(primitiveset);
2582
2583                    unsigned int primCount=0;
2584                    for(DrawElementsUByte::const_iterator primItr=drawElements->begin();
2585                        primItr!=drawElements->end();
2586                        ++primCount,++primItr)
2587                    {
2588                        if ((primCount%primLength)==0)
2589                        {
2590                            primitiveNum++;
2591                        }
2592                        unsigned int vindex = *primItr;
2593                        if (vindex > maxVertexNumber) maxVertexNumber = vindex;
2594                    }
2595
2596                    break;
2597                }
2598                case(PrimitiveSet::DrawElementsUShortPrimitiveType):
2599                {
2600                    if (primLength==0) primLength=primitiveset->getNumIndices();
2601
2602                    const DrawElementsUShort* drawElements = static_cast<const DrawElementsUShort*>(primitiveset);
2603                    unsigned int primCount=0;
2604                    for(DrawElementsUShort::const_iterator primItr=drawElements->begin();
2605                        primItr!=drawElements->end();
2606                        ++primCount,++primItr)
2607                    {
2608                        if ((primCount%primLength)==0)
2609                        {
2610                            primitiveNum++;
2611                        }
2612                        unsigned int vindex = *primItr;
2613                        if (vindex > maxVertexNumber) maxVertexNumber = vindex;
2614                    }
2615
2616                    break;
2617                }
2618                case(PrimitiveSet::DrawElementsUIntPrimitiveType):
2619                {
2620                    if (primLength==0) primLength=primitiveset->getNumIndices();
2621
2622                    const DrawElementsUInt* drawElements = static_cast<const DrawElementsUInt*>(primitiveset);
2623                    unsigned int primCount=0;
2624                    for(DrawElementsUInt::const_iterator primItr=drawElements->begin();
2625                        primItr!=drawElements->end();
2626                        ++primCount,++primItr)
2627                    {
2628                        if ((primCount%primLength)==0)
2629                        {
2630                            primitiveNum++;
2631                        }
2632                        unsigned int vindex = *primItr;
2633                        if (vindex > maxVertexNumber) maxVertexNumber = vindex;
2634                    }
2635                    break;
2636                }
2637                default:
2638                {
2639                    break;
2640                }
2641            }
2642        }
2643    }
2644
2645    bool validArray(std::ostream& out, const osg::Geometry::ArrayData& arrayData, const char* arrayName)
2646    {
2647        unsigned int numRequired = 0;
2648        switch(arrayData.binding)
2649        {
2650            case(osg::Geometry::BIND_OFF): numRequired = 0; break;
2651            case(osg::Geometry::BIND_OVERALL): numRequired = 1; break;
2652            case(osg::Geometry::BIND_PER_PRIMITIVE): numRequired = primitiveNum; break;
2653            case(osg::Geometry::BIND_PER_PRIMITIVE_SET): numRequired = numPrimitiveSets; break;
2654            case(osg::Geometry::BIND_PER_VERTEX): numRequired = maxVertexNumber+1; break;
2655        }
2656
2657        if (arrayData.indices.valid())
2658        {
2659            unsigned int numIndices= arrayData.indices.valid() ? arrayData.indices->getNumElements() : 0;
2660            if (numIndices<numRequired)
2661            {
2662                out<<"Not enough "<<arrayName<<" indices, numRequired="<<numRequired<<std::endl;
2663                return false;
2664            }
2665
2666            unsigned int numNormals = arrayData.array.valid() ? arrayData.array->getNumElements() : 0;
2667            for(unsigned int i=0; i<numIndices; ++i)
2668            {
2669                if (arrayData.indices->index(i)>=numNormals)
2670                {
2671                    out<<arrayName<<" index out of bounds of normal array"<<std::endl;
2672                    return false;
2673                }
2674            }
2675        }
2676        else
2677        {
2678            unsigned int numElements = arrayData.array.valid() ? arrayData.array->getNumElements() : 0;
2679            if (numElements<numRequired)
2680            {
2681                out<<"Not enough "<<arrayName<<", numRequired="<<numRequired<<", but number in array="<<numElements<<std::endl;
2682                return false;
2683            }
2684        }
2685        return true;
2686    }
2687
2688    unsigned int numPrimitiveSets;
2689    unsigned int primitiveNum;
2690    unsigned int maxVertexNumber;
2691
2692};
2693
2694bool Geometry::verifyArrays(std::ostream& out) const
2695{
2696    CheckArrayValidity cav(this);
2697
2698    bool result = true;
2699
2700    if (!cav.validArray(out, _vertexData, "Vertex")) result = false;
2701    if (!cav.validArray(out, _normalData, "Normal")) result = false;
2702    if (!cav.validArray(out, _colorData, "Color")) result = false;
2703    if (!cav.validArray(out, _secondaryColorData, "SecondaryColor")) result = false;
2704    if (!cav.validArray(out, _fogCoordData, "FogCoord")) result = false;
2705
2706    for(unsigned int ti=0;ti<_texCoordList.size();++ti)
2707    {
2708        if (!cav.validArray(out, _texCoordList[ti], "TexCoord")) result = false;
2709    }
2710
2711    for(unsigned int vi=0;vi<_vertexAttribList.size();++vi)
2712    {
2713        if (!cav.validArray(out, _vertexAttribList[vi], "TexCoord")) result = false;
2714    }
2715
2716    return result;
2717}
2718
2719Geometry* osg::createTexturedQuadGeometry(const Vec3& corner,const Vec3& widthVec,const Vec3& heightVec, float l, float b, float r, float t)
2720{
2721    Geometry* geom = new Geometry;
2722
2723    Vec3Array* coords = new Vec3Array(4);
2724    (*coords)[0] = corner+heightVec;
2725    (*coords)[1] = corner;
2726    (*coords)[2] = corner+widthVec;
2727    (*coords)[3] = corner+widthVec+heightVec;
2728    geom->setVertexArray(coords);
2729
2730    Vec2Array* tcoords = new Vec2Array(4);
2731    (*tcoords)[0].set(l,t);
2732    (*tcoords)[1].set(l,b);
2733    (*tcoords)[2].set(r,b);
2734    (*tcoords)[3].set(r,t);
2735    geom->setTexCoordArray(0,tcoords);
2736
2737    osg::Vec4Array* colours = new osg::Vec4Array(1);
2738    (*colours)[0].set(1.0f,1.0f,1.0,1.0f);
2739    geom->setColorArray(colours);
2740    geom->setColorBinding(Geometry::BIND_OVERALL);
2741
2742    osg::Vec3Array* normals = new osg::Vec3Array(1);
2743    (*normals)[0] = widthVec^heightVec;
2744    (*normals)[0].normalize();
2745    geom->setNormalArray(normals);
2746    geom->setNormalBinding(Geometry::BIND_OVERALL);
2747
2748    geom->addPrimitiveSet(new DrawArrays(PrimitiveSet::QUADS,0,4));
2749
2750    return geom;
2751}
Note: See TracBrowser for help on using the browser.