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

Revision 10874, 89.6 kB (checked in by robert, 5 years ago)

Added a Geometry::compileGLObjects() to handle compilation of VBO + EBO's.

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