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

Revision 11202, 89.2 kB (checked in by robert, 5 years ago)

Clean up of initialization of statics/use of getenv

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