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

Revision 10670, 86.0 kB (checked in by robert, 4 years ago)

Removed old and now redundent code paths

  • 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::drawImplementation(RenderInfo& renderInfo) const
908{
909    State& state = *renderInfo.getState();
910    Drawable::Extensions* extensions = Drawable::getExtensions(state.getContextID(),true);
911
912    bool useFastPath = areFastPathsUsed();
913    bool usingVertexBufferObjects = _useVertexBufferObjects && state.isVertexBufferObjectSupported();
914    bool handleVertexAttributes = !_vertexAttribList.empty() && extensions->isVertexProgramSupported();
915
916    ArrayDispatchers& arrayDispatchers = state.getArrayDispatchers();
917
918    arrayDispatchers.setUseVertexAttribAlias(state.getUseVertexAttributeAliasing());
919    arrayDispatchers.reset();
920    // arrayDispatchers.setUseGLBeginEndAdapter(!useFastPath);
921
922    arrayDispatchers.activateNormalArray(_normalData.binding, _normalData.array.get(), _normalData.indices.get());
923    arrayDispatchers.activateColorArray(_colorData.binding, _colorData.array.get(), _colorData.indices.get());
924    arrayDispatchers.activateSecondaryColorArray(_secondaryColorData.binding, _secondaryColorData.array.get(), _secondaryColorData.indices.get());
925    arrayDispatchers.activateFogCoordArray(_fogCoordData.binding, _fogCoordData.array.get(), _fogCoordData.indices.get());
926
927    if (handleVertexAttributes)
928    {
929        for(unsigned int unit=0;unit<_vertexAttribList.size();++unit)
930        {
931            arrayDispatchers.activateVertexAttribArray(_vertexAttribList[unit].binding, unit, _vertexAttribList[unit].array.get(), _vertexAttribList[unit].indices.get());
932        }
933    }
934
935    // dispatch any attributes that are bound overall
936    arrayDispatchers.dispatch(BIND_OVERALL,0);
937
938    state.lazyDisablingOfVertexAttributes();
939
940    if (useFastPath)
941    {
942        // set up arrays
943        if( _vertexData.array.valid() )
944            state.setVertexPointer(_vertexData.array.get());
945
946        if (_normalData.binding==BIND_PER_VERTEX && _normalData.array.valid())
947            state.setNormalPointer(_normalData.array.get());
948
949        if (_colorData.binding==BIND_PER_VERTEX && _colorData.array.valid())
950            state.setColorPointer(_colorData.array.get());
951
952        if (_secondaryColorData.binding==BIND_PER_VERTEX && _secondaryColorData.array.valid())
953            state.setSecondaryColorPointer(_secondaryColorData.array.get());
954
955        if (_fogCoordData.binding==BIND_PER_VERTEX && _fogCoordData.array.valid())
956            state.setFogCoordPointer(_fogCoordData.array.get());
957
958        for(unsigned int unit=0;unit<_texCoordList.size();++unit)
959        {
960            const Array* array = _texCoordList[unit].array.get();
961            if (array) state.setTexCoordPointer(unit,array);
962        }
963
964        if( handleVertexAttributes )
965        {
966            for(unsigned int index = 0; index < _vertexAttribList.size(); ++index )
967            {
968                const Array* array = _vertexAttribList[index].array.get();
969                const AttributeBinding ab = _vertexAttribList[index].binding;
970                if( ab == BIND_PER_VERTEX && array )
971                {
972                    state.setVertexAttribPointer( index, array, _vertexAttribList[index].normalize );
973                }
974            }
975        }
976    }
977    else
978    {
979        for(unsigned int unit=0;unit<_texCoordList.size();++unit)
980        {
981            arrayDispatchers.activateTexCoordArray(BIND_PER_VERTEX, unit, _texCoordList[unit].array.get(), _texCoordList[unit].indices.get());
982        }
983
984        arrayDispatchers.activateVertexArray(BIND_PER_VERTEX, _vertexData.array.get(), _vertexData.indices.get());
985    }
986
987    state.applyDisablingOfVertexAttributes();
988
989    bool bindPerPrimtiveSetActive = arrayDispatchers.active(BIND_PER_PRIMITIVE_SET);
990    bool bindPerPrimtiveActive = arrayDispatchers.active(BIND_PER_PRIMITIVE);
991
992    unsigned int primitiveNum = 0;
993
994    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
995    //
996    // draw the primitives themselves.
997    //
998    for(unsigned int primitiveSetNum=0; primitiveSetNum!=_primitives.size(); ++primitiveSetNum)
999    {
1000
1001        // dispatch any attributes that are bound per primitive
1002        if (bindPerPrimtiveSetActive) arrayDispatchers.dispatch(BIND_PER_PRIMITIVE_SET, primitiveSetNum);
1003
1004        const PrimitiveSet* primitiveset = _primitives[primitiveSetNum].get();
1005
1006        if (useFastPath)
1007        {
1008            primitiveset->draw(state, usingVertexBufferObjects);
1009        }
1010        else
1011        {
1012            GLenum mode=primitiveset->getMode();
1013
1014            unsigned int primLength;
1015            switch(mode)
1016            {
1017                case(GL_POINTS):    primLength=1; break;
1018                case(GL_LINES):     primLength=2; break;
1019                case(GL_TRIANGLES): primLength=3; break;
1020                case(GL_QUADS):     primLength=4; break;
1021                default:            primLength=0; break; // compute later when =0.
1022            }
1023
1024            // draw primitives by the more flexible "slow" path,
1025            // sending OpenGL glBegin/glVertex.../glEnd().
1026            switch(primitiveset->getType())
1027            {
1028                case(PrimitiveSet::DrawArraysPrimitiveType):
1029                {
1030                    if (primLength==0) primLength=primitiveset->getNumIndices();
1031
1032                    const DrawArrays* drawArray = static_cast<const DrawArrays*>(primitiveset);
1033                    arrayDispatchers.Begin(mode);
1034
1035                    unsigned int primCount=0;
1036                    unsigned int indexEnd = drawArray->getFirst()+drawArray->getCount();
1037                    for(unsigned int vindex=drawArray->getFirst();
1038                        vindex<indexEnd;
1039                        ++vindex,++primCount)
1040                    {
1041                        if (bindPerPrimtiveActive && (primCount%primLength)==0)
1042                        {
1043                            arrayDispatchers.dispatch(BIND_PER_PRIMITIVE,++primitiveNum);
1044                        }
1045
1046                        arrayDispatchers.dispatch(BIND_PER_VERTEX, vindex);
1047                    }
1048
1049                    arrayDispatchers.End();
1050                    break;
1051                }
1052                case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
1053                {
1054                    const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
1055                    unsigned int vindex=drawArrayLengths->getFirst();
1056                    for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
1057                        primItr!=drawArrayLengths->end();
1058                        ++primItr)
1059                    {
1060                        unsigned int localPrimLength;
1061                        if (primLength==0) localPrimLength=*primItr;
1062                        else localPrimLength=primLength;
1063
1064                        arrayDispatchers.Begin(mode);
1065
1066                        for(GLsizei primCount=0;
1067                            primCount<*primItr;
1068                            ++vindex,++primCount)
1069                        {
1070                            if (bindPerPrimtiveActive && (primCount%localPrimLength)==0)
1071                            {
1072                                arrayDispatchers.dispatch(BIND_PER_PRIMITIVE, ++primitiveNum);
1073                            }
1074                            arrayDispatchers.dispatch(BIND_PER_VERTEX, vindex);
1075                        }
1076
1077                        arrayDispatchers.End();
1078
1079                    }
1080                    break;
1081                }
1082                case(PrimitiveSet::DrawElementsUBytePrimitiveType):
1083                {
1084                    if (primLength==0) primLength=primitiveset->getNumIndices();
1085
1086                    const DrawElementsUByte* drawElements = static_cast<const DrawElementsUByte*>(primitiveset);
1087                    arrayDispatchers.Begin(mode);
1088
1089                    unsigned int primCount=0;
1090                    for(DrawElementsUByte::const_iterator primItr=drawElements->begin();
1091                        primItr!=drawElements->end();
1092                        ++primCount,++primItr)
1093                    {
1094
1095                        if (bindPerPrimtiveActive && (primCount%primLength)==0)
1096                        {
1097                            arrayDispatchers.dispatch(BIND_PER_PRIMITIVE, ++primitiveNum);
1098                        }
1099
1100                        unsigned int vindex=*primItr;
1101                        arrayDispatchers.dispatch(BIND_PER_VERTEX, vindex);
1102                    }
1103
1104                    arrayDispatchers.End();
1105                    break;
1106                }
1107                case(PrimitiveSet::DrawElementsUShortPrimitiveType):
1108                {
1109                    if (primLength==0) primLength=primitiveset->getNumIndices();
1110
1111                    const DrawElementsUShort* drawElements = static_cast<const DrawElementsUShort*>(primitiveset);
1112                    arrayDispatchers.Begin(mode);
1113
1114                    unsigned int primCount=0;
1115                    for(DrawElementsUShort::const_iterator primItr=drawElements->begin();
1116                        primItr!=drawElements->end();
1117                        ++primCount,++primItr)
1118                    {
1119                        if (bindPerPrimtiveActive && (primCount%primLength)==0)
1120                        {
1121                            arrayDispatchers.dispatch(BIND_PER_PRIMITIVE, ++primitiveNum);
1122                        }
1123
1124                        unsigned int vindex=*primItr;
1125                        arrayDispatchers.dispatch(BIND_PER_VERTEX, vindex);
1126                    }
1127
1128                    arrayDispatchers.End();
1129                    break;
1130                }
1131                case(PrimitiveSet::DrawElementsUIntPrimitiveType):
1132                {
1133                    if (primLength==0) primLength=primitiveset->getNumIndices();
1134
1135                    const DrawElementsUInt* drawElements = static_cast<const DrawElementsUInt*>(primitiveset);
1136                    arrayDispatchers.Begin(mode);
1137
1138                    unsigned int primCount=0;
1139                    for(DrawElementsUInt::const_iterator primItr=drawElements->begin();
1140                        primItr!=drawElements->end();
1141                        ++primCount,++primItr)
1142                    {
1143                        if (bindPerPrimtiveActive && (primCount%primLength)==0)
1144                        {
1145                            arrayDispatchers.dispatch(BIND_PER_PRIMITIVE, ++primitiveNum);
1146                        }
1147
1148                        unsigned int vindex=*primItr;
1149                        arrayDispatchers.dispatch(BIND_PER_VERTEX, vindex);
1150                    }
1151
1152                    arrayDispatchers.End();
1153                    break;
1154                }
1155                default:
1156                {
1157                    break;
1158                }
1159            }
1160        }
1161    }
1162}
1163
1164class AttributeFunctorArrayVisitor : public ArrayVisitor
1165{
1166    public:
1167   
1168        AttributeFunctorArrayVisitor(Drawable::AttributeFunctor& af):
1169            _af(af) {}
1170   
1171        virtual ~AttributeFunctorArrayVisitor() {}
1172
1173        virtual void apply(ByteArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1174        virtual void apply(ShortArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1175        virtual void apply(IntArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1176        virtual void apply(UByteArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1177        virtual void apply(UShortArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1178        virtual void apply(UIntArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1179        virtual void apply(Vec4ubArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1180        virtual void apply(FloatArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1181        virtual void apply(Vec2Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1182        virtual void apply(Vec3Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1183        virtual void apply(Vec4Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1184        virtual void apply(DoubleArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1185        virtual void apply(Vec2dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1186        virtual void apply(Vec3dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1187        virtual void apply(Vec4dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1188   
1189   
1190        inline void applyArray(Drawable::AttributeType type,Array* array)
1191        {
1192            if (array)
1193            {
1194                _type = type;
1195                array->accept(*this);
1196            }
1197        }
1198
1199    protected:       
1200       
1201        AttributeFunctorArrayVisitor& operator = (const AttributeFunctorArrayVisitor&) { return *this; }
1202        Drawable::AttributeFunctor&   _af;
1203        Drawable::AttributeType       _type;
1204};
1205
1206void Geometry::accept(AttributeFunctor& af)
1207{
1208    AttributeFunctorArrayVisitor afav(af);
1209
1210    if (_vertexData.array.valid())
1211    {
1212        afav.applyArray(VERTICES,_vertexData.array.get());
1213    }
1214    else if (_vertexAttribList.size()>0)
1215    {
1216        osg::notify(osg::INFO)<<"Geometry::accept(AttributeFunctor& af): Using vertex attribute instead"<<std::endl;
1217        afav.applyArray(VERTICES,_vertexAttribList[0].array.get());
1218    }
1219
1220    afav.applyArray(NORMALS,_normalData.array.get());
1221    afav.applyArray(COLORS,_colorData.array.get());
1222    afav.applyArray(SECONDARY_COLORS,_secondaryColorData.array.get());
1223    afav.applyArray(FOG_COORDS,_fogCoordData.array.get());
1224   
1225    for(unsigned unit=0;unit<_texCoordList.size();++unit)
1226    {
1227        afav.applyArray((AttributeType)(TEXTURE_COORDS_0+unit),_texCoordList[unit].array.get());
1228    }
1229
1230    for(unsigned int index=0; index<_vertexAttribList.size(); ++index)
1231    {
1232        afav.applyArray(index,_vertexAttribList[index].array.get());
1233    }
1234}
1235
1236class ConstAttributeFunctorArrayVisitor : public ConstArrayVisitor
1237{
1238    public:
1239   
1240        ConstAttributeFunctorArrayVisitor(Drawable::ConstAttributeFunctor& af):
1241            _af(af) {}
1242   
1243        virtual ~ConstAttributeFunctorArrayVisitor() {}
1244
1245        virtual void apply(const ByteArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1246        virtual void apply(const ShortArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1247        virtual void apply(const IntArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1248        virtual void apply(const UByteArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1249        virtual void apply(const UShortArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1250        virtual void apply(const UIntArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1251        virtual void apply(const Vec4ubArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1252        virtual void apply(const FloatArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1253        virtual void apply(const Vec2Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1254        virtual void apply(const Vec3Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1255        virtual void apply(const Vec4Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1256        virtual void apply(const DoubleArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1257        virtual void apply(const Vec2dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1258        virtual void apply(const Vec3dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1259        virtual void apply(const Vec4dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
1260   
1261   
1262        inline void applyArray(Drawable::AttributeType type,const Array* array)
1263        {
1264            if (array)
1265            {
1266                _type = type;
1267                array->accept(*this);
1268            }
1269        }
1270   
1271protected:
1272
1273        ConstAttributeFunctorArrayVisitor& operator = (const ConstAttributeFunctorArrayVisitor&) { return *this; }
1274
1275        Drawable::ConstAttributeFunctor&    _af;
1276        Drawable::AttributeType             _type;
1277};
1278
1279void Geometry::accept(ConstAttributeFunctor& af) const
1280{
1281    ConstAttributeFunctorArrayVisitor afav(af);
1282   
1283    if (_vertexData.array.valid())
1284    {
1285        afav.applyArray(VERTICES,_vertexData.array.get());
1286    }
1287    else if (_vertexAttribList.size()>0)
1288    {
1289        osg::notify(osg::INFO)<<"Geometry::accept(ConstAttributeFunctor& af): Using vertex attribute instead"<<std::endl;
1290        afav.applyArray(VERTICES,_vertexAttribList[0].array.get());
1291    }
1292
1293    afav.applyArray(NORMALS,_normalData.array.get());
1294    afav.applyArray(COLORS,_colorData.array.get());
1295    afav.applyArray(SECONDARY_COLORS,_secondaryColorData.array.get());
1296    afav.applyArray(FOG_COORDS,_fogCoordData.array.get());
1297
1298    for(unsigned unit=0;unit<_texCoordList.size();++unit)
1299    {
1300        afav.applyArray((AttributeType)(TEXTURE_COORDS_0+unit),_texCoordList[unit].array.get());
1301    }
1302
1303    for(unsigned int index=0; index<_vertexAttribList.size(); ++index)
1304    {
1305        afav.applyArray(index,_vertexAttribList[index].array.get());
1306    }
1307}
1308
1309void Geometry::accept(PrimitiveFunctor& functor) const
1310{
1311    const osg::Array* vertices = _vertexData.array.get();
1312    const osg::IndexArray* indices = _vertexData.indices.get();
1313
1314    if (!vertices && _vertexAttribList.size()>0)
1315    {
1316        osg::notify(osg::INFO)<<"Using vertex attribute instead"<<std::endl;
1317        vertices = _vertexAttribList[0].array.get();
1318        indices = _vertexAttribList[0].indices.get();
1319    }
1320
1321    if (!vertices || vertices->getNumElements()==0) return;
1322
1323    if (!indices)
1324    {
1325        switch(vertices->getType())
1326        {
1327        case(Array::Vec2ArrayType):
1328            functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec2*>(vertices->getDataPointer()));
1329            break;
1330        case(Array::Vec3ArrayType):
1331            functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec3*>(vertices->getDataPointer()));
1332            break;
1333        case(Array::Vec4ArrayType):
1334            functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec4*>(vertices->getDataPointer()));
1335            break;
1336        case(Array::Vec2dArrayType):
1337            functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec2d*>(vertices->getDataPointer()));
1338            break;
1339        case(Array::Vec3dArrayType):
1340            functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec3d*>(vertices->getDataPointer()));
1341            break;
1342        case(Array::Vec4dArrayType):
1343            functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec4d*>(vertices->getDataPointer()));
1344            break;
1345        default:
1346            notify(WARN)<<"Warning: Geometry::accept(PrimitiveFunctor&) cannot handle Vertex Array type"<<vertices->getType()<<std::endl;
1347            return;
1348        }
1349       
1350        for(PrimitiveSetList::const_iterator itr=_primitives.begin();
1351            itr!=_primitives.end();
1352            ++itr)
1353        {
1354            (*itr)->accept(functor);
1355        }
1356    }
1357    else
1358    {
1359        const Vec2* vec2Array = 0;
1360        const Vec3* vec3Array = 0;
1361        const Vec4* vec4Array = 0;
1362        const Vec2d* vec2dArray = 0;
1363        const Vec3d* vec3dArray = 0;
1364        const Vec4d* vec4dArray = 0;
1365        Array::Type type = vertices->getType();
1366        switch(type)
1367        {
1368        case(Array::Vec2ArrayType):
1369            vec2Array = static_cast<const Vec2*>(vertices->getDataPointer());
1370            break;
1371        case(Array::Vec3ArrayType):
1372            vec3Array = static_cast<const Vec3*>(vertices->getDataPointer());
1373            break;
1374        case(Array::Vec4ArrayType):
1375            vec4Array = static_cast<const Vec4*>(vertices->getDataPointer());
1376            break;
1377        case(Array::Vec2dArrayType):
1378            vec2dArray = static_cast<const Vec2d*>(vertices->getDataPointer());
1379            break;
1380        case(Array::Vec3dArrayType):
1381            vec3dArray = static_cast<const Vec3d*>(vertices->getDataPointer());
1382            break;
1383        case(Array::Vec4dArrayType):
1384            vec4dArray = static_cast<const Vec4d*>(vertices->getDataPointer());
1385            break;
1386        default:
1387            notify(WARN)<<"Warning: Geometry::accept(PrimitiveFunctor&) cannot handle Vertex Array type"<<vertices->getType()<<std::endl;
1388            return;
1389        }
1390
1391        for(PrimitiveSetList::const_iterator itr=_primitives.begin();
1392            itr!=_primitives.end();
1393            ++itr)
1394        {
1395            const PrimitiveSet* primitiveset = itr->get();
1396            GLenum mode=primitiveset->getMode();
1397            switch(primitiveset->getType())
1398            {
1399                case(PrimitiveSet::DrawArraysPrimitiveType):
1400                {
1401                    const DrawArrays* drawArray = static_cast<const DrawArrays*>(primitiveset);
1402                    functor.begin(mode);
1403
1404                    unsigned int indexEnd = drawArray->getFirst()+drawArray->getCount();
1405                    for(unsigned int vindex=drawArray->getFirst();
1406                        vindex<indexEnd;
1407                        ++vindex)
1408                    {
1409                        switch(type)
1410                        {
1411                        case(Array::Vec2ArrayType):
1412                            functor.vertex(vec2Array[_vertexData.indices->index(vindex)]);
1413                            break;
1414                        case(Array::Vec3ArrayType):
1415                            functor.vertex(vec3Array[_vertexData.indices->index(vindex)]);
1416                            break;
1417                        case(Array::Vec4ArrayType):
1418                            functor.vertex(vec4Array[_vertexData.indices->index(vindex)]);
1419                            break;
1420                        case(Array::Vec2dArrayType):
1421                            functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]);
1422                            break;
1423                        case(Array::Vec3dArrayType):
1424                            functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]);
1425                            break;
1426                        case(Array::Vec4dArrayType):
1427                            functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]);
1428                            break;
1429                        default:
1430                            break;
1431                        }
1432
1433                    }
1434
1435                    functor.end();
1436                    break;
1437                }
1438                case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
1439                {
1440
1441                    const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
1442                    unsigned int vindex=drawArrayLengths->getFirst();
1443                    for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
1444                        primItr!=drawArrayLengths->end();
1445                        ++primItr)
1446                    {
1447
1448                        functor.begin(mode);
1449
1450                        for(GLsizei primCount=0;primCount<*primItr;++primCount)
1451                        {
1452                            switch(type)
1453                            {
1454                            case(Array::Vec2ArrayType):
1455                                functor.vertex(vec2Array[_vertexData.indices->index(vindex)]);
1456                                break;
1457                            case(Array::Vec3ArrayType):
1458                                functor.vertex(vec3Array[_vertexData.indices->index(vindex)]);
1459                                break;
1460                            case(Array::Vec4ArrayType):
1461                                functor.vertex(vec4Array[_vertexData.indices->index(vindex)]);
1462                                break;
1463                            case(Array::Vec2dArrayType):
1464                                functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]);
1465                                break;
1466                            case(Array::Vec3dArrayType):
1467                                functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]);
1468                                break;
1469                            case(Array::Vec4dArrayType):
1470                                functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]);
1471                                break;
1472                            default:
1473                                break;
1474                            }
1475                            ++vindex;
1476                        }
1477
1478                        functor.end();
1479
1480                    }
1481                    break;
1482                }
1483                case(PrimitiveSet::DrawElementsUBytePrimitiveType):
1484                {
1485                    const DrawElementsUByte* drawElements = static_cast<const DrawElementsUByte*>(primitiveset);
1486                    functor.begin(mode);
1487
1488                    unsigned int primCount=0;
1489                    for(DrawElementsUByte::const_iterator primItr=drawElements->begin();
1490                        primItr!=drawElements->end();
1491                        ++primCount,++primItr)
1492                    {
1493                        unsigned int vindex=*primItr;
1494                        switch(type)
1495                        {
1496                        case(Array::Vec2ArrayType):
1497                            functor.vertex(vec2Array[_vertexData.indices->index(vindex)]);
1498                            break;
1499                        case(Array::Vec3ArrayType):
1500                            functor.vertex(vec3Array[_vertexData.indices->index(vindex)]);
1501                            break;
1502                        case(Array::Vec4ArrayType):
1503                            functor.vertex(vec4Array[_vertexData.indices->index(vindex)]);
1504                            break;
1505                        case(Array::Vec2dArrayType):
1506                            functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]);
1507                            break;
1508                        case(Array::Vec3dArrayType):
1509                            functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]);
1510                            break;
1511                        case(Array::Vec4dArrayType):
1512                            functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]);
1513                            break;
1514                        default:
1515                            break;
1516                        }
1517                    }
1518
1519                    functor.end();
1520                    break;
1521                }
1522                case(PrimitiveSet::DrawElementsUShortPrimitiveType):
1523                {
1524                    const DrawElementsUShort* drawElements = static_cast<const DrawElementsUShort*>(primitiveset);
1525                    functor.begin(mode);
1526
1527                    for(DrawElementsUShort::const_iterator primItr=drawElements->begin();
1528                        primItr!=drawElements->end();
1529                        ++primItr)
1530                    {
1531                        unsigned int vindex=*primItr;
1532                        switch(type)
1533                        {
1534                        case(Array::Vec2ArrayType):
1535                            functor.vertex(vec2Array[_vertexData.indices->index(vindex)]);
1536                            break;
1537                        case(Array::Vec3ArrayType):
1538                            functor.vertex(vec3Array[_vertexData.indices->index(vindex)]);
1539                            break;
1540                        case(Array::Vec4ArrayType):
1541                            functor.vertex(vec4Array[_vertexData.indices->index(vindex)]);
1542                            break;
1543                        case(Array::Vec2dArrayType):
1544                            functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]);
1545                            break;
1546                        case(Array::Vec3dArrayType):
1547                            functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]);
1548                            break;
1549                        case(Array::Vec4dArrayType):
1550                            functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]);
1551                            break;
1552                        default:
1553                            break;
1554                        }
1555                    }
1556
1557                    functor.end();
1558                    break;
1559                }
1560                case(PrimitiveSet::DrawElementsUIntPrimitiveType):
1561                {
1562                    const DrawElementsUInt* drawElements = static_cast<const DrawElementsUInt*>(primitiveset);
1563                    functor.begin(mode);
1564
1565                    for(DrawElementsUInt::const_iterator primItr=drawElements->begin();
1566                        primItr!=drawElements->end();
1567                        ++primItr)
1568                    {
1569                        unsigned int vindex=*primItr;
1570                        switch(type)
1571                        {
1572                        case(Array::Vec2ArrayType):
1573                            functor.vertex(vec2Array[_vertexData.indices->index(vindex)]);
1574                            break;
1575                        case(Array::Vec3ArrayType):
1576                            functor.vertex(vec3Array[_vertexData.indices->index(vindex)]);
1577                            break;
1578                        case(Array::Vec4ArrayType):
1579                            functor.vertex(vec4Array[_vertexData.indices->index(vindex)]);
1580                            break;
1581                        case(Array::Vec2dArrayType):
1582                            functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]);
1583                            break;
1584                        case(Array::Vec3dArrayType):
1585                            functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]);
1586                            break;
1587                        case(Array::Vec4dArrayType):
1588                            functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]);
1589                            break;
1590                        default:
1591                            break;
1592                        }
1593                    }
1594
1595                    functor.end();
1596                    break;
1597                }
1598                default:
1599                {
1600                    break;
1601                }
1602            }
1603        }
1604    }
1605    return;
1606}
1607
1608void Geometry::accept(PrimitiveIndexFunctor& functor) const
1609{
1610    const osg::Array* vertices = _vertexData.array.get();
1611    const osg::IndexArray* indices = _vertexData.indices.get();
1612
1613    if (!vertices && _vertexAttribList.size()>0)
1614    {
1615        osg::notify(osg::INFO)<<"Geometry::accept(PrimitiveIndexFunctor& functor): Using vertex attribute instead"<<std::endl;
1616        vertices = _vertexAttribList[0].array.get();
1617        indices = _vertexAttribList[0].indices.get();
1618    }
1619
1620    if (!vertices || vertices->getNumElements()==0) return;
1621
1622    switch(vertices->getType())
1623    {
1624    case(Array::Vec2ArrayType):
1625        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec2*>(vertices->getDataPointer()));
1626        break;
1627    case(Array::Vec3ArrayType):
1628        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec3*>(vertices->getDataPointer()));
1629        break;
1630    case(Array::Vec4ArrayType):
1631        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec4*>(vertices->getDataPointer()));
1632        break;
1633    case(Array::Vec2dArrayType):
1634        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec2d*>(vertices->getDataPointer()));
1635        break;
1636    case(Array::Vec3dArrayType):
1637        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec3d*>(vertices->getDataPointer()));
1638        break;
1639    case(Array::Vec4dArrayType):
1640        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec4d*>(vertices->getDataPointer()));
1641        break;
1642    default:
1643        notify(WARN)<<"Warning: Geometry::accept(PrimitiveIndexFunctor&) cannot handle Vertex Array type"<<vertices->getType()<<std::endl;
1644        return;
1645    }
1646
1647    if (!_vertexData.indices.valid())
1648    {
1649        for(PrimitiveSetList::const_iterator itr=_primitives.begin();
1650            itr!=_primitives.end();
1651            ++itr)
1652        {
1653            (*itr)->accept(functor);
1654        }
1655    }
1656    else
1657    {
1658        for(PrimitiveSetList::const_iterator itr=_primitives.begin();
1659            itr!=_primitives.end();
1660            ++itr)
1661        {
1662            const PrimitiveSet* primitiveset = itr->get();
1663            GLenum mode=primitiveset->getMode();
1664            switch(primitiveset->getType())
1665            {
1666                case(PrimitiveSet::DrawArraysPrimitiveType):
1667                {
1668                    const DrawArrays* drawArray = static_cast<const DrawArrays*>(primitiveset);
1669                    functor.begin(mode);
1670
1671                    unsigned int indexEnd = drawArray->getFirst()+drawArray->getCount();
1672                    for(unsigned int vindex=drawArray->getFirst();
1673                        vindex<indexEnd;
1674                        ++vindex)
1675                    {
1676                        functor.vertex(_vertexData.indices->index(vindex));
1677                    }
1678                   
1679                    functor.end();
1680                    break;
1681                }
1682                case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
1683                {
1684
1685                    const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
1686                    unsigned int vindex=drawArrayLengths->getFirst();
1687                    for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
1688                        primItr!=drawArrayLengths->end();
1689                        ++primItr)
1690                    {
1691
1692                        functor.begin(mode);
1693
1694                        for(GLsizei primCount=0;primCount<*primItr;++primCount)
1695                        {
1696                            functor.vertex(_vertexData.indices->index(vindex));
1697                            ++vindex;
1698                        }
1699                       
1700                        functor.end();
1701
1702                    }
1703                    break;
1704                }
1705                case(PrimitiveSet::DrawElementsUBytePrimitiveType):
1706                {
1707                    const DrawElementsUByte* drawElements = static_cast<const DrawElementsUByte*>(primitiveset);
1708                    functor.begin(mode);
1709
1710                    unsigned int primCount=0;
1711                    for(DrawElementsUByte::const_iterator primItr=drawElements->begin();
1712                        primItr!=drawElements->end();
1713                        ++primCount,++primItr)
1714                    {
1715                        unsigned int vindex=*primItr;
1716                        functor.vertex(_vertexData.indices->index(vindex));
1717                    }
1718
1719                    functor.end();
1720                    break;
1721                }
1722                case(PrimitiveSet::DrawElementsUShortPrimitiveType):
1723                {
1724                    const DrawElementsUShort* drawElements = static_cast<const DrawElementsUShort*>(primitiveset);
1725                    functor.begin(mode);
1726
1727                    for(DrawElementsUShort::const_iterator primItr=drawElements->begin();
1728                        primItr!=drawElements->end();
1729                        ++primItr)
1730                    {
1731                        unsigned int vindex=*primItr;
1732                        functor.vertex(_vertexData.indices->index(vindex));
1733                    }
1734
1735                    functor.end();
1736                    break;
1737                }
1738                case(PrimitiveSet::DrawElementsUIntPrimitiveType):
1739                {
1740                    const DrawElementsUInt* drawElements = static_cast<const DrawElementsUInt*>(primitiveset);
1741                    functor.begin(mode);
1742
1743                    for(DrawElementsUInt::const_iterator primItr=drawElements->begin();
1744                        primItr!=drawElements->end();
1745                        ++primItr)
1746                    {
1747                        unsigned int vindex=*primItr;
1748                        functor.vertex(_vertexData.indices->index(vindex));
1749                    }
1750
1751                    functor.end();
1752                    break;
1753                }
1754                default:
1755                {
1756                    break;
1757                }
1758            }
1759        }
1760    }
1761    return;
1762}
1763
1764unsigned int _computeNumberOfPrimitives(const osg::Geometry& geom)
1765{
1766
1767    unsigned int totalNumberOfPrimitives = 0;
1768   
1769    for(Geometry::PrimitiveSetList::const_iterator itr=geom.getPrimitiveSetList().begin();
1770        itr!=geom.getPrimitiveSetList().end();
1771        ++itr)
1772    {
1773        const PrimitiveSet* primitiveset = itr->get();
1774        GLenum mode=primitiveset->getMode();
1775
1776        unsigned int primLength;
1777        switch(mode)
1778        {
1779            case(GL_POINTS):    primLength=1; osg::notify(osg::INFO)<<"prim=GL_POINTS"<<std::endl; break;
1780            case(GL_LINES):     primLength=2; osg::notify(osg::INFO)<<"prim=GL_LINES"<<std::endl; break;
1781            case(GL_TRIANGLES): primLength=3; osg::notify(osg::INFO)<<"prim=GL_TRIANGLES"<<std::endl; break;
1782            case(GL_QUADS):     primLength=4; osg::notify(osg::INFO)<<"prim=GL_QUADS"<<std::endl; break;
1783            default:            primLength=0; osg::notify(osg::INFO)<<"prim="<<std::hex<<mode<<std::dec<<std::endl; break; // compute later when =0.
1784        }
1785
1786        // draw primitives by the more flexible "slow" path,
1787        // sending OpenGL Begin/glVertex.../End().
1788        switch(primitiveset->getType())
1789        {
1790            case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
1791            {
1792
1793                const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
1794                for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
1795                    primItr!=drawArrayLengths->end();
1796                    ++primItr)
1797                {
1798                    if (primLength==0) totalNumberOfPrimitives += 1;
1799                    else totalNumberOfPrimitives += *primItr/primLength;
1800                }
1801                break;
1802            }
1803            default:
1804            {
1805                if (primLength==0) { totalNumberOfPrimitives += 1; osg::notify(osg::INFO)<<"   totalNumberOfPrimitives="<<totalNumberOfPrimitives<<std::endl;}
1806                else { totalNumberOfPrimitives += primitiveset->getNumIndices()/primLength; osg::notify(osg::INFO)<<"   primitiveset->getNumIndices()="<<primitiveset->getNumIndices()<<" totalNumberOfPrimitives="<<totalNumberOfPrimitives<<std::endl; }
1807
1808            }
1809        }
1810    }
1811
1812    return totalNumberOfPrimitives;
1813}
1814
1815template<class A>
1816bool _verifyBindings(const osg::Geometry& geom, const A& arrayData)
1817{
1818    unsigned int numElements = arrayData.indices.valid()?arrayData.indices->getNumElements():
1819                               arrayData.array.valid()?arrayData.array->getNumElements():0;
1820
1821    switch(arrayData.binding)
1822    {
1823        case(osg::Geometry::BIND_OFF):
1824            if (numElements>0) return false;
1825            break;
1826        case(osg::Geometry::BIND_OVERALL):
1827            if (numElements!=1) return false;
1828            break;
1829        case(osg::Geometry::BIND_PER_PRIMITIVE_SET):
1830            if (numElements!=geom.getPrimitiveSetList().size()) return false;
1831            break;
1832        case(osg::Geometry::BIND_PER_PRIMITIVE):
1833            if (numElements!=_computeNumberOfPrimitives(geom)) return false;
1834            break;
1835        case(osg::Geometry::BIND_PER_VERTEX):
1836        {
1837            unsigned int numVertices = geom.getVertexIndices()?geom.getVertexIndices()->getNumElements():
1838                                       geom.getVertexArray()?geom.getVertexArray()->getNumElements():0;
1839            if (numElements!=numVertices) return false;       
1840            break;
1841        }
1842    }
1843    return true;
1844}
1845
1846template<class A>
1847void _computeCorrectBindingsAndArraySizes(std::ostream& out, const osg::Geometry& geom, A& arrayData, const char* arrayName)
1848{
1849    unsigned int numElements = arrayData.indices.valid()?arrayData.indices->getNumElements():
1850                               arrayData.array.valid()?arrayData.array->getNumElements():0;
1851
1852    // check to see if binding matches 0 elements required.
1853    if (numElements==0)
1854    {
1855        // correct binding if not correct.
1856        if (arrayData.binding!=osg::Geometry::BIND_OFF)
1857        {
1858            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() "<<std::endl
1859                   <<"         "<<arrayName<<" binding has been reset to BIND_OFF"<<std::endl;
1860            arrayData.binding=osg::Geometry::BIND_OFF;
1861        }
1862        return;
1863    }
1864
1865    // check to see if binding matches 1 elements required.
1866    if (numElements==1)
1867    {
1868        // correct binding if not correct.
1869        if (arrayData.binding!=osg::Geometry::BIND_OVERALL)
1870        {
1871            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() "<<std::endl
1872                   <<"         "<<arrayName<<" binding has been reset to BIND_OVERALL"<<std::endl;
1873            arrayData.binding=osg::Geometry::BIND_OVERALL;
1874        }
1875        return;
1876    }
1877
1878
1879    unsigned int numVertices = geom.getVertexIndices()?geom.getVertexIndices()->getNumElements():
1880                               geom.getVertexArray()?geom.getVertexArray()->getNumElements():0;
1881   
1882    if ( numVertices==0 )
1883    {
1884        if (arrayData.binding!=osg::Geometry::BIND_OFF)
1885        {
1886            arrayData.array = 0;
1887            arrayData.indices = 0;
1888            arrayData.binding = osg::Geometry::BIND_OFF;
1889            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() vertex array is empty but "<<std::endl
1890                <<"         vertex array is empty but"<<arrayName<<" is set"<<std::endl
1891                <<"         reseting "<<arrayName<< " binding to BIND_OFF and array & indices to 0."<<std::endl;
1892        }
1893    }
1894   
1895    if (numElements==numVertices)
1896    {
1897        // correct the binding to per vertex.
1898        if (arrayData.binding!=osg::Geometry::BIND_PER_VERTEX)
1899        {
1900            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() "<<std::endl
1901                   <<"         "<<arrayName<<" binding has been reset to BIND_PER_VERTEX"<<std::endl;
1902            arrayData.binding = osg::Geometry::BIND_PER_VERTEX;
1903        }
1904        return;
1905    }
1906
1907
1908
1909    // check to see if binding might be per primitive set   
1910    unsigned int numPrimitiveSets = geom.getPrimitiveSetList().size();
1911   
1912    if (numElements==numPrimitiveSets)
1913    {
1914        if (arrayData.binding != osg::Geometry::BIND_PER_PRIMITIVE_SET)
1915        {
1916            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() "<<std::endl
1917                   <<"         "<<arrayName<<" binding has been reset to BIND_PER_PRIMITIVE_SET"<<std::endl;
1918            arrayData.binding = osg::Geometry::BIND_PER_PRIMITIVE_SET;
1919        }
1920        return;
1921    }
1922   
1923    // check to see if binding might be per primitive   
1924    unsigned int numPrimitives = _computeNumberOfPrimitives(geom);
1925    if (numElements==numPrimitives)
1926    {
1927        if (arrayData.binding != osg::Geometry::BIND_PER_PRIMITIVE)
1928        {
1929            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() "<<std::endl
1930                   <<"         "<<arrayName<<" binding has been reset to BIND_PER_PRIMITIVE"<<std::endl;
1931            arrayData.binding = osg::Geometry::BIND_PER_PRIMITIVE;
1932        }
1933        return;
1934    }
1935
1936    if (numElements>numVertices)
1937    {
1938        arrayData.binding = osg::Geometry::BIND_PER_VERTEX;
1939        return;
1940    }
1941    if (numElements>numPrimitives)
1942    {
1943        arrayData.binding = osg::Geometry::BIND_PER_PRIMITIVE;
1944        return;
1945    }
1946    if (numElements>numPrimitiveSets)
1947    {
1948        arrayData.binding = osg::Geometry::BIND_PER_PRIMITIVE_SET;
1949        return;
1950    }
1951    if (numElements>=1)
1952    {
1953        arrayData.binding = osg::Geometry::BIND_OVERALL;
1954        return;
1955    }
1956    arrayData.binding = osg::Geometry::BIND_OFF;
1957 
1958}       
1959
1960bool Geometry::verifyBindings(const ArrayData& arrayData) const
1961{
1962    return _verifyBindings(*this,arrayData);
1963}
1964
1965bool Geometry::verifyBindings(const Vec3ArrayData& arrayData) const
1966{
1967    return _verifyBindings(*this,arrayData);
1968}
1969
1970void Geometry::computeCorrectBindingsAndArraySizes(ArrayData& arrayData, const char* arrayName)
1971{
1972    _computeCorrectBindingsAndArraySizes(osg::notify(osg::INFO),*this,arrayData,arrayName);
1973}
1974
1975void Geometry::computeCorrectBindingsAndArraySizes(Vec3ArrayData& arrayData, const char* arrayName)
1976{
1977    _computeCorrectBindingsAndArraySizes(osg::notify(osg::INFO),*this,arrayData,arrayName);
1978}
1979
1980bool Geometry::verifyBindings() const
1981{
1982    if (!verifyBindings(_normalData)) return false;
1983    if (!verifyBindings(_colorData)) return false;
1984    if (!verifyBindings(_secondaryColorData)) return false;
1985    if (!verifyBindings(_fogCoordData)) return false;
1986
1987    for(ArrayDataList::const_iterator titr=_texCoordList.begin();
1988        titr!=_texCoordList.end();
1989        ++titr)
1990    {
1991        if (!verifyBindings(*titr)) return false;
1992    }
1993
1994    for(ArrayDataList::const_iterator vitr=_vertexAttribList.begin();
1995        vitr!=_vertexAttribList.end();
1996        ++vitr)
1997    {
1998        if (!verifyBindings(*vitr)) return false;
1999    }
2000
2001    return true;
2002}
2003
2004void Geometry::computeCorrectBindingsAndArraySizes()
2005{
2006    // if (verifyBindings()) return;
2007   
2008    computeCorrectBindingsAndArraySizes(_normalData,"_normalData");
2009    computeCorrectBindingsAndArraySizes(_colorData,"_colorData");
2010    computeCorrectBindingsAndArraySizes(_secondaryColorData,"_secondaryColorData");
2011    computeCorrectBindingsAndArraySizes(_fogCoordData,"_fogCoordData");
2012
2013    for(ArrayDataList::iterator titr=_texCoordList.begin();
2014        titr!=_texCoordList.end();
2015        ++titr)
2016    {
2017        computeCorrectBindingsAndArraySizes(*titr,"_texCoordList[]");
2018    }
2019
2020    for(ArrayDataList::iterator vitr=_vertexAttribList.begin();
2021        vitr!=_vertexAttribList.end();
2022        ++vitr)
2023    {
2024        computeCorrectBindingsAndArraySizes(*vitr,"_vertAttribList[]");
2025    }
2026}
2027
2028class ExpandIndexedArray : public osg::ConstArrayVisitor
2029{
2030    public:
2031        ExpandIndexedArray(const osg::IndexArray& indices,Array* targetArray):
2032            _indices(indices),
2033            _targetArray(targetArray) {}
2034       
2035        virtual ~ExpandIndexedArray() {}
2036
2037        // Create when both of the arrays are predefined templated classes. We
2038        // can do some optimizations in this case that aren't possible in the general
2039        // case.
2040        template <class T,class I>
2041        T* create_inline(const T& array,const I& indices)
2042        {
2043            T* newArray = 0;
2044
2045            // if source array type and target array type are equal but arrays arn't equal
2046            if (_targetArray && _targetArray->getType()==array.getType() && _targetArray!=(osg::Array*)(&array))
2047            {
2048                // reuse exisiting target array
2049                newArray = static_cast<T*>(_targetArray);
2050                if (newArray->size()!=indices.size())
2051                {
2052                    // make sure its the right size
2053                    newArray->resize(indices.size());
2054                }
2055            }
2056            else
2057            {
2058                //  else create a new array.
2059                newArray = new T(indices.size());
2060            }
2061
2062            for(unsigned int i=0;i<indices.size();++i)
2063            {
2064                (*newArray)[i]= array[indices[i]];
2065            }
2066
2067            return newArray;
2068        }
2069
2070        // Create when one of the arrays isn't one of the predefined templated classes. The
2071        // template parameter is the type of the array that will get created. This is  always
2072        // one of the predefined classes. We could call clone to get one of the same type as
2073        // the input array, but the interface of the osg::Array class doesn't include a way
2074        // to set an element.
2075        template <class T>
2076        osg::Array* create_noinline(const osg::Array& array, const osg::IndexArray& indices)
2077        {
2078            T* newArray = 0;
2079            typedef typename T::ElementDataType EDT;
2080
2081            unsigned int num_indices = indices.getNumElements();
2082            newArray = new T(num_indices);
2083
2084            const EDT* src = static_cast<const EDT*>(array.getDataPointer());
2085
2086            for(unsigned int i=0;i<num_indices;++i)
2087            {
2088                (*newArray)[i]= src[indices.index(i)];
2089            }
2090
2091            return newArray;
2092        }
2093
2094        osg::Array* create_noinline(const osg::Array& array, const osg::IndexArray& indices)
2095        {
2096            switch (array.getType())
2097            {
2098                case(osg::Array::ByteArrayType):   return create_noinline<osg::ByteArray>(array,indices);
2099                case(osg::Array::ShortArrayType):  return create_noinline<osg::ShortArray>(array,indices);
2100                case(osg::Array::IntArrayType):    return create_noinline<osg::IntArray>(array,indices);
2101                case(osg::Array::UByteArrayType):  return create_noinline<osg::UByteArray>(array,indices);
2102                case(osg::Array::UShortArrayType): return create_noinline<osg::UShortArray>(array,indices);
2103                case(osg::Array::UIntArrayType):   return create_noinline<osg::UIntArray>(array,indices);
2104                case(osg::Array::Vec4ubArrayType): return create_noinline<osg::Vec4ubArray>(array,indices);
2105                case(osg::Array::FloatArrayType):  return create_noinline<osg::FloatArray>(array,indices);
2106                case(osg::Array::Vec2ArrayType):   return create_noinline<osg::Vec2Array>(array,indices);
2107                case(osg::Array::Vec3ArrayType):   return create_noinline<osg::Vec3Array>(array,indices);
2108                case(osg::Array::Vec4ArrayType):   return create_noinline<osg::Vec4Array>(array,indices);
2109                case(osg::Array::Vec2dArrayType):   return create_noinline<osg::Vec2dArray>(array,indices);
2110                case(osg::Array::Vec3dArrayType):   return create_noinline<osg::Vec3dArray>(array,indices);
2111                case(osg::Array::Vec4dArrayType):   return create_noinline<osg::Vec4dArray>(array,indices);
2112                default:
2113                    return NULL;
2114            }
2115        }
2116
2117        template <class TA, class TI>
2118        osg::Array* create(const TA& array, const osg::IndexArray& indices)
2119        {
2120            // We know that indices.getType returned the same thing as TI, but
2121            // we need to determine whether it is really an instance of TI, or
2122            // perhaps another subclass of osg::Array that contains the same
2123            // type of data.
2124            const TI* ba(dynamic_cast<const TI*>(&indices));
2125            if (ba != NULL) {
2126                return create_inline(array,*ba);
2127            }
2128            else {
2129                return create_noinline(array, _indices);
2130            }
2131        }
2132
2133        template <class T>
2134        osg::Array* create(const T& array)
2135        {
2136            switch(_indices.getType())
2137            {
2138            case(osg::Array::ByteArrayType):   return create<T, osg::ByteArray>(array, _indices);
2139            case(osg::Array::ShortArrayType):  return create<T, osg::ShortArray>(array, _indices);
2140            case(osg::Array::IntArrayType):    return create<T, osg::IntArray>(array, _indices);
2141            case(osg::Array::UByteArrayType):  return create<T, osg::UByteArray>(array, _indices);
2142            case(osg::Array::UShortArrayType): return create<T, osg::UShortArray>(array, _indices);
2143            case(osg::Array::UIntArrayType):   return create<T, osg::UIntArray>(array, _indices);
2144            default:                           return create_noinline(array, _indices);
2145            }
2146           
2147        }
2148
2149        // applys for the predefined classes go through 1-arg create to do indexing
2150        virtual void apply(const osg::ByteArray& array) { _targetArray = create(array); }
2151        virtual void apply(const osg::ShortArray& array) { _targetArray = create(array); }
2152        virtual void apply(const osg::IntArray& array) { _targetArray = create(array); }
2153        virtual void apply(const osg::UByteArray& array) { _targetArray = create(array); }
2154        virtual void apply(const osg::UShortArray& array) { _targetArray = create(array); }
2155        virtual void apply(const osg::UIntArray& array) { _targetArray = create(array); }
2156        virtual void apply(const osg::Vec4ubArray& array) { _targetArray = create(array); }
2157        virtual void apply(const osg::FloatArray& array) { _targetArray = create(array); }
2158        virtual void apply(const osg::Vec2Array& array) { _targetArray = create(array); }
2159        virtual void apply(const osg::Vec3Array& array) { _targetArray = create(array); }
2160        virtual void apply(const osg::Vec4Array& array) { _targetArray = create(array); }
2161
2162        // other subclasses of osg::Array end up here
2163        virtual void apply(const osg::Array& array) { _targetArray = create_noinline(array, _indices); }
2164
2165        const osg::IndexArray& _indices;
2166        osg::Array* _targetArray;
2167
2168    protected:
2169
2170        ExpandIndexedArray& operator = (const ExpandIndexedArray&) { return *this; }
2171
2172};
2173
2174bool Geometry::suitableForOptimization() const
2175{
2176    bool hasIndices = false;
2177
2178    if (getVertexIndices()) hasIndices = true;
2179
2180    if (getNormalIndices()) hasIndices = true;
2181
2182    if (getColorIndices()) hasIndices = true;
2183
2184    if (getSecondaryColorIndices()) hasIndices = true;
2185
2186    if (getFogCoordIndices()) hasIndices = true;
2187
2188    for(unsigned int ti=0;ti<getNumTexCoordArrays();++ti)
2189    {
2190        if (getTexCoordIndices(ti)) hasIndices = true;
2191    }
2192   
2193    for(unsigned int vi=0;vi<getNumVertexAttribArrays();++vi)
2194    {
2195        if (getVertexAttribIndices(vi)) hasIndices = true;
2196    }
2197
2198    return hasIndices;
2199}
2200
2201void Geometry::copyToAndOptimize(Geometry& target)
2202{
2203    bool copyToSelf = (this==&target);
2204
2205    // copy over primitive sets.
2206    if (!copyToSelf) target.getPrimitiveSetList() = getPrimitiveSetList();
2207
2208    // copy over attribute arrays.
2209    if (getVertexIndices() && getVertexArray())
2210    {
2211        ExpandIndexedArray eia(*(getVertexIndices()),target.getVertexArray());
2212        getVertexArray()->accept(eia);
2213
2214        target.setVertexArray(eia._targetArray);
2215        target.setVertexIndices(0);
2216    }
2217    else if (getVertexArray())
2218    {
2219        if (!copyToSelf) target.setVertexArray(getVertexArray());
2220    }
2221
2222    target.setNormalBinding(getNormalBinding());
2223    if (getNormalIndices() && getNormalArray())
2224    {
2225        ExpandIndexedArray eia(*(getNormalIndices()),target.getNormalArray());
2226        getNormalArray()->accept(eia);
2227
2228        target.setNormalArray(dynamic_cast<osg::Vec3Array*>(eia._targetArray));
2229        target.setNormalIndices(0);
2230    }
2231    else if (getNormalArray())
2232    {
2233        if (!copyToSelf) target.setNormalArray(getNormalArray());
2234    }
2235
2236    target.setColorBinding(getColorBinding());
2237    if (getColorIndices() && getColorArray())
2238    {
2239        ExpandIndexedArray eia(*(getColorIndices()),target.getColorArray());
2240        getColorArray()->accept(eia);
2241
2242        target.setColorArray(eia._targetArray);
2243        target.setColorIndices(0);
2244    }
2245    else if (getColorArray())
2246    {
2247        if (!copyToSelf) target.setColorArray(getColorArray());
2248    }
2249
2250    target.setSecondaryColorBinding(getSecondaryColorBinding());
2251    if (getSecondaryColorIndices() && getSecondaryColorArray())
2252    {
2253        ExpandIndexedArray eia(*(getSecondaryColorIndices()),target.getSecondaryColorArray());
2254        getSecondaryColorArray()->accept(eia);
2255
2256        target.setSecondaryColorArray(eia._targetArray);
2257        target.setSecondaryColorIndices(0);
2258    }
2259    else if (getSecondaryColorArray())
2260    {
2261        if (!copyToSelf) target.setSecondaryColorArray(getSecondaryColorArray());
2262    }
2263
2264    target.setFogCoordBinding(getFogCoordBinding());
2265    if (getFogCoordIndices() && getFogCoordArray())
2266    {
2267        ExpandIndexedArray eia(*(getFogCoordIndices()),target.getFogCoordArray());
2268        getFogCoordArray()->accept(eia);
2269
2270        target.setFogCoordArray(eia._targetArray);
2271        target.setFogCoordIndices(0);
2272    }
2273    else if (getFogCoordArray())
2274    {
2275        if (!copyToSelf) target.setFogCoordArray(getFogCoordArray());
2276    }
2277
2278    for(unsigned int ti=0;ti<getNumTexCoordArrays();++ti)
2279    {
2280        if (getTexCoordIndices(ti) && getTexCoordArray(ti))
2281        {
2282            ExpandIndexedArray eia(*(getTexCoordIndices(ti)),target.getTexCoordArray(ti));
2283           
2284            getTexCoordArray(ti)->accept(eia);
2285
2286            target.setTexCoordArray(ti,eia._targetArray);
2287            target.setTexCoordIndices(ti,0);
2288        }
2289        else if (getTexCoordArray(ti))
2290        {
2291            if (!copyToSelf) target.setTexCoordArray(ti,getTexCoordArray(ti));
2292        }
2293    }
2294   
2295    for(unsigned int vi=0;vi<_vertexAttribList.size();++vi)
2296    {
2297        ArrayData& arrayData = _vertexAttribList[vi];
2298        if (arrayData.indices.valid())
2299        {
2300            ExpandIndexedArray eia(*arrayData.indices,target.getVertexAttribArray(vi));
2301            arrayData.array->accept(eia);
2302            target.setVertexAttribData(vi,ArrayData(eia._targetArray, 0, arrayData.binding, arrayData.normalize));
2303        }
2304        else if (arrayData.array.valid())
2305        {
2306            if (!copyToSelf) target.setVertexAttribData(vi,arrayData);
2307        }
2308    }
2309}
2310
2311bool Geometry::containsSharedArrays() const
2312{
2313    unsigned int numSharedArrays = 0;
2314   
2315    if (getVertexArray() && getVertexArray()->referenceCount()>1) ++numSharedArrays;
2316    if (getNormalArray() && getNormalArray()->referenceCount()>1) ++numSharedArrays;
2317    if (getColorArray() && getColorArray()->referenceCount()>1) ++numSharedArrays;
2318    if (getSecondaryColorArray() && getSecondaryColorArray()->referenceCount()>1) ++numSharedArrays;
2319    if (getFogCoordArray() && getFogCoordArray()->referenceCount()>1) ++numSharedArrays;
2320
2321    for(unsigned int ti=0;ti<getNumTexCoordArrays();++ti)
2322    {
2323        if (getTexCoordArray(ti) && getTexCoordArray(ti)->referenceCount()>1) ++numSharedArrays;
2324    }
2325   
2326    for(unsigned int vi=0;vi<_vertexAttribList.size();++vi)
2327    {
2328        const ArrayData& arrayData = _vertexAttribList[vi];
2329        if (arrayData.array.valid() && arrayData.array->referenceCount()>1) ++numSharedArrays;
2330    }
2331    return numSharedArrays!=0;
2332}
2333
2334void Geometry::duplicateSharedArrays()
2335{
2336    #define DUPLICATE_IF_REQUIRED(A) \
2337        if (get##A() && get##A()->referenceCount()>1) \
2338        { \
2339            set##A(dynamic_cast<osg::Array*>(get##A()->clone(osg::CopyOp::DEEP_COPY_ARRAYS))); \
2340        }
2341
2342    DUPLICATE_IF_REQUIRED(VertexArray)
2343    DUPLICATE_IF_REQUIRED(NormalArray)
2344    DUPLICATE_IF_REQUIRED(ColorArray)
2345    DUPLICATE_IF_REQUIRED(SecondaryColorArray)
2346    DUPLICATE_IF_REQUIRED(FogCoordArray)
2347
2348    for(unsigned int ti=0;ti<getNumTexCoordArrays();++ti)
2349    {
2350        if (getTexCoordArray(ti) && getTexCoordArray(ti)->referenceCount()>1)
2351        {
2352            setTexCoordArray(ti, dynamic_cast<osg::Array*>(getTexCoordArray(ti)->clone(osg::CopyOp::DEEP_COPY_ARRAYS)));
2353        }
2354    }
2355   
2356    for(unsigned int vi=0;vi<_vertexAttribList.size();++vi)
2357    {
2358        ArrayData& arrayData = _vertexAttribList[vi];
2359        if (arrayData.array.valid() && arrayData.array->referenceCount()>1)
2360        {
2361            arrayData.array = dynamic_cast<osg::Array*>(arrayData.array->clone(osg::CopyOp::DEEP_COPY_ARRAYS));
2362        }
2363    }
2364}
2365
2366void Geometry::computeInternalOptimizedGeometry()
2367{
2368    if (suitableForOptimization())
2369    {
2370        if (!_internalOptimizedGeometry) _internalOptimizedGeometry = new Geometry;
2371
2372        copyToAndOptimize(*_internalOptimizedGeometry);
2373    }
2374}
2375
2376
2377Geometry* osg::createTexturedQuadGeometry(const Vec3& corner,const Vec3& widthVec,const Vec3& heightVec, float l, float b, float r, float t)
2378{
2379    Geometry* geom = new Geometry;
2380
2381    Vec3Array* coords = new Vec3Array(4);
2382    (*coords)[0] = corner+heightVec;
2383    (*coords)[1] = corner;
2384    (*coords)[2] = corner+widthVec;
2385    (*coords)[3] = corner+widthVec+heightVec;
2386    geom->setVertexArray(coords);
2387
2388    Vec2Array* tcoords = new Vec2Array(4);
2389    (*tcoords)[0].set(l,t);
2390    (*tcoords)[1].set(l,b);
2391    (*tcoords)[2].set(r,b);
2392    (*tcoords)[3].set(r,t);
2393    geom->setTexCoordArray(0,tcoords);
2394
2395    osg::Vec4Array* colours = new osg::Vec4Array(1);
2396    (*colours)[0].set(1.0f,1.0f,1.0,1.0f);
2397    geom->setColorArray(colours);
2398    geom->setColorBinding(Geometry::BIND_OVERALL);
2399
2400    osg::Vec3Array* normals = new osg::Vec3Array(1);
2401    (*normals)[0] = widthVec^heightVec;
2402    (*normals)[0].normalize();
2403    geom->setNormalArray(normals);
2404    geom->setNormalBinding(Geometry::BIND_OVERALL);
2405
2406    geom->addPrimitiveSet(new DrawArrays(PrimitiveSet::QUADS,0,4));
2407
2408    return geom;
2409}
Note: See TracBrowser for help on using the browser.