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

Revision 10654, 156.6 kB (checked in by robert, 5 years ago)

Removed the disabling of display lists in osg::Geometry to bring it back to it's original behaviour

  • 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
23// #define USE_OLD_DRAW_IMPLEMENTATOIN
24
25#ifdef USE_OLD_DRAW_IMPLEMENTATOIN
26class DrawVertex
27{
28    public:
29   
30        DrawVertex(const Array* vertices,const IndexArray* indices):
31            _vertices(vertices),
32            _indices(indices)
33        {
34            _verticesType = _vertices?_vertices->getType():Array::ArrayType;
35            _indicesType = _indices?_indices->getType():Array::ArrayType;
36        }
37   
38        inline unsigned int index(unsigned int pos)
39        {
40            if (_indices)
41            {
42                return _indices->index(pos);
43            }
44            else 
45            {
46                return 0;
47            }
48        }
49
50        inline void operator () (unsigned int pos)
51        {
52            if (_indices) pos = index(pos);
53
54            switch(_verticesType)
55            {
56            case(Array::Vec3ArrayType):
57                apply(static_cast<const Vec3*>(_vertices->getDataPointer())[pos]);
58                break;
59            case(Array::Vec2ArrayType):
60                apply(static_cast<const Vec2*>(_vertices->getDataPointer())[pos]);
61                break;
62            case(Array::Vec4ArrayType):
63                apply(static_cast<const Vec4*>(_vertices->getDataPointer())[pos]);
64                break;
65            case(Array::Vec3dArrayType):
66                apply(static_cast<const Vec3d*>(_vertices->getDataPointer())[pos]);
67                break;
68            case(Array::Vec2dArrayType):
69                apply(static_cast<const Vec2d*>(_vertices->getDataPointer())[pos]);
70                break;
71            case(Array::Vec4dArrayType):
72                apply(static_cast<const Vec4d*>(_vertices->getDataPointer())[pos]);
73                break;
74            default:
75                break;
76            }
77           
78        }
79       
80        inline void apply(const Vec2& v)   { glVertex2fv(v.ptr()); }
81        inline void apply(const Vec3& v)   { glVertex3fv(v.ptr()); }
82        inline void apply(const Vec4& v)   { glVertex4fv(v.ptr()); }
83        inline void apply(const Vec2d& v)   { glVertex2dv(v.ptr()); }
84        inline void apply(const Vec3d& v)   { glVertex3dv(v.ptr()); }
85        inline void apply(const Vec4d& v)   { glVertex4dv(v.ptr()); }
86
87        const Array*        _vertices;
88        const IndexArray*   _indices;
89        Array::Type         _verticesType;
90        Array::Type         _indicesType;
91};
92
93class DrawNormal
94{
95    public:
96   
97        DrawNormal(const Array* normals,const IndexArray* indices):
98            _normals(normals),
99            _indices(indices)
100        {
101            _normalsType = normals?normals->getType():Array::ArrayType;
102        }
103   
104        void operator () (unsigned int pos)
105        {
106            switch(_normalsType)
107            {
108                case (Array::Vec3ArrayType):
109                    {
110                        const Vec3* normals(static_cast<const Vec3*>(_normals->getDataPointer()));
111                        if (_indices) glNormal3fv(normals[_indices->index(pos)].ptr());
112                        else glNormal3fv(normals[pos].ptr());
113                    }
114                    break;
115                case (Array::Vec3sArrayType):
116                    {
117                        const Vec3s* normals(static_cast<const Vec3s*>(_normals->getDataPointer()));
118                        if (_indices) glNormal3sv(normals[_indices->index(pos)].ptr());
119                        else glNormal3sv(normals[pos].ptr());
120                    }
121                    break;
122                case (Array::Vec4sArrayType):
123                    {
124                        const Vec4s* normals(static_cast<const Vec4s*>(_normals->getDataPointer()));
125                        if (_indices) glNormal3sv(normals[_indices->index(pos)].ptr());
126                        else glNormal3sv(normals[pos].ptr());
127                    }
128                    break;
129                case (Array::Vec3bArrayType):
130                    {
131                        const Vec3b* normals(static_cast<const Vec3b*>(_normals->getDataPointer()));
132                        if (_indices) glNormal3bv((const GLbyte*)normals[_indices->index(pos)].ptr());
133                        else glNormal3bv((const GLbyte*)normals[pos].ptr());
134                    }
135                    break;
136                case (Array::Vec4bArrayType):
137                    {
138                        const Vec4b* normals(static_cast<const Vec4b*>(_normals->getDataPointer()));
139                        if (_indices) glNormal3bv((const GLbyte*)normals[_indices->index(pos)].ptr());
140                        else glNormal3bv((const GLbyte*)normals[pos].ptr());
141                    }
142                    break;
143                case (Array::Vec3dArrayType):
144                    {
145                        const Vec3d* normals(static_cast<const Vec3d*>(_normals->getDataPointer()));
146                        if (_indices) glNormal3dv(normals[_indices->index(pos)].ptr());
147                        else glNormal3dv(normals[pos].ptr());
148                    }
149                    break;
150                case (Array::Vec4dArrayType):
151                    {
152                        const Vec4d* normals(static_cast<const Vec4d*>(_normals->getDataPointer()));
153                        if (_indices) glNormal3dv(normals[_indices->index(pos)].ptr());
154                        else glNormal3dv(normals[pos].ptr());
155                    }
156                    break;
157                default:
158                    break;
159                   
160            }
161        }
162       
163        const Array*       _normals;
164        const IndexArray*  _indices;
165        Array::Type        _normalsType;
166};
167
168class DrawColor
169{
170    public:
171
172        DrawColor(const Array* colors,const IndexArray* indices):
173            _colors(colors),
174            _indices(indices)
175        {
176            _colorsType = _colors?_colors->getType():Array::ArrayType;
177            _indicesType = _indices?_indices->getType():Array::ArrayType;
178        }
179
180        inline unsigned int index(unsigned int pos)
181        {
182            if (_indices) {
183                return _indices->index(pos);
184            }
185            else {
186                return 0;
187            }
188        }
189
190        inline void operator () (unsigned int pos)
191        {
192            if (_indices) pos = index(pos);
193
194            switch(_colorsType)
195            {
196            case(Array::Vec4ArrayType):
197                apply(static_cast<const Vec4*>(_colors->getDataPointer())[pos]);
198                break;
199            case(Array::Vec4ubArrayType):
200                apply(static_cast<const Vec4ub*>(_colors->getDataPointer())[pos]);
201                break;
202            case(Array::Vec3ArrayType):
203                apply(static_cast<const Vec3*>(_colors->getDataPointer())[pos]);
204                break;
205            case(Array::Vec3dArrayType):
206                apply(static_cast<const Vec3d*>(_colors->getDataPointer())[pos]);
207                break;
208            case(Array::Vec4dArrayType):
209                apply(static_cast<const Vec4d*>(_colors->getDataPointer())[pos]);
210                break;
211            default:
212                break;
213            }
214        }
215
216        inline void apply(const Vec4ub& v) { glColor4ubv(v.ptr()); }
217        inline void apply(const Vec3& v)   { glColor3fv(v.ptr()); }
218        inline void apply(const Vec4& v)   { glColor4fv(v.ptr()); }
219       
220        const Array*        _colors;
221        const IndexArray*   _indices;
222        Array::Type         _colorsType;
223        Array::Type         _indicesType;
224};
225
226class DrawVertexAttrib : public osg::Referenced, public osg::ConstValueVisitor
227{
228public:
229
230    DrawVertexAttrib(const Drawable::Extensions * extensions,unsigned int vertAttribIndex,GLboolean normalized,const Array* attribcoords,const IndexArray* indices):
231            _vertAttribIndex(vertAttribIndex),
232            _normalized(normalized),
233            _extensions(extensions),
234            _attribcoords(attribcoords),
235            _indices(indices),
236            _index(0) {;}
237           
238    inline void applyAndIncrement() { operator()(_index++); }
239
240    inline void operator () (unsigned int pos)
241    {
242        if (_indices) _attribcoords->accept(_indices->index(pos),*this);
243        else _attribcoords->accept(pos,*this);
244    }
245
246    virtual void apply(const GLshort& s)
247    {
248        _extensions->glVertexAttrib1s( _vertAttribIndex, s );
249    }
250    virtual void apply(const GLfloat& f)
251    {
252        _extensions->glVertexAttrib1f( _vertAttribIndex, f );
253    }
254    virtual void apply(const Vec4ub& v)
255    {
256        if( _normalized )
257        {
258            _extensions->glVertexAttrib4Nubv( _vertAttribIndex, v.ptr() );
259        }
260        else
261        {
262            _extensions->glVertexAttrib4ubv( _vertAttribIndex, v.ptr() );
263        }
264    }
265    virtual void apply(const Vec2& v)
266    {
267        _extensions->glVertexAttrib2fv( _vertAttribIndex, v.ptr() );
268    }
269    virtual void apply(const Vec3& v)
270    {
271        _extensions->glVertexAttrib3fv( _vertAttribIndex, v.ptr() );
272    }
273    virtual void apply(const Vec4& v)
274    {
275        _extensions->glVertexAttrib4fv( _vertAttribIndex, v.ptr() );
276    }
277    virtual void apply(const Vec2d& v)
278    {
279        _extensions->glVertexAttrib2dv( _vertAttribIndex, v.ptr() );
280    }
281    virtual void apply(const Vec3d& v)
282    {
283        _extensions->glVertexAttrib3dv( _vertAttribIndex, v.ptr() );
284    }
285    virtual void apply(const Vec4d& v)
286    {
287        _extensions->glVertexAttrib4dv( _vertAttribIndex, v.ptr() );
288    }
289
290    unsigned int                    _vertAttribIndex;
291    GLboolean                       _normalized;
292    const Drawable::Extensions*     _extensions;
293    const Array*                    _attribcoords;
294    const IndexArray*               _indices;
295    unsigned int                    _index;
296};
297
298class DrawTexCoord : public osg::Referenced, public osg::ConstValueVisitor
299{
300    public:
301
302        DrawTexCoord(const Array* texcoords,const IndexArray* indices):
303            _texcoords(texcoords),
304            _indices(indices) {}
305
306        inline void operator () (unsigned int pos)
307        {
308            if (_indices) _texcoords->accept(_indices->index(pos),*this);
309            else _texcoords->accept(pos,*this);
310        }
311
312        virtual void apply(const GLfloat& v){ glTexCoord1f(v); }
313        virtual void apply(const Vec2& v)   { glTexCoord2fv(v.ptr()); }
314        virtual void apply(const Vec3& v)   { glTexCoord3fv(v.ptr()); }
315        virtual void apply(const Vec4& v)   { glTexCoord4fv(v.ptr()); }
316
317        const Array*        _texcoords;
318        const IndexArray*   _indices;
319};
320
321class DrawMultiTexCoord : public osg::Referenced, public osg::ConstValueVisitor
322{
323    public:
324   
325        DrawMultiTexCoord(GLenum target,const Array* texcoords,const IndexArray* indices,
326            const Drawable::Extensions * extensions):
327            _target(target),
328            _texcoords(texcoords),
329            _indices(indices),
330            _extensions(extensions) {}
331
332        inline void operator () (unsigned int pos)
333        {
334            if (_indices) _texcoords->accept(_indices->index(pos),*this);
335            else _texcoords->accept(pos,*this);
336        }
337
338        virtual void apply(const GLfloat& v){ _extensions->glMultiTexCoord1f(_target,v); }
339        virtual void apply(const Vec2& v)   { _extensions->glMultiTexCoord2fv(_target,v.ptr()); }
340        virtual void apply(const Vec3& v)   { _extensions->glMultiTexCoord3fv(_target,v.ptr()); }
341        virtual void apply(const Vec4& v)   { _extensions->glMultiTexCoord4fv(_target,v.ptr()); }
342       
343        GLenum              _target;
344        const Array*        _texcoords;
345        const IndexArray*   _indices;
346
347        const Drawable::Extensions * _extensions;
348};
349
350
351class DrawSecondaryColor : public osg::ConstValueVisitor
352{
353    public:
354   
355        DrawSecondaryColor(const Array* colors,const IndexArray* indices,
356                           const Drawable::Extensions * extensions):
357            _colors(colors),
358            _indices(indices),
359            _extensions(extensions)
360            {}
361   
362        inline void operator () (unsigned int pos)
363        {
364            if (_indices) _colors->accept(_indices->index(pos),*this);
365            else _colors->accept(pos,*this);
366        }
367
368        virtual void apply(const Vec4ub& v) { _extensions->glSecondaryColor3ubv(v.ptr()); }
369        virtual void apply(const Vec3& v)   { _extensions->glSecondaryColor3fv(v.ptr()); }
370        virtual void apply(const Vec4& v)   { _extensions->glSecondaryColor3fv(v.ptr()); }
371
372        const Array*        _colors;
373        const IndexArray*   _indices;
374
375        const Drawable::Extensions * _extensions;
376};
377
378class DrawFogCoord : public osg::ConstValueVisitor
379{
380    public:
381   
382        DrawFogCoord(const Array* fogcoords,const IndexArray* indices,const Drawable::Extensions * extensions):
383            _fogcoords(fogcoords),
384            _indices(indices),
385            _extensions(extensions) {}
386   
387        inline void operator () (unsigned int pos)
388        {
389            if (_indices) _fogcoords->accept(_indices->index(pos),*this);
390            else _fogcoords->accept(pos,*this);
391        }
392
393        virtual void apply(const GLfloat& v) { _extensions->glFogCoordfv(&v); }
394
395        const Array*        _fogcoords;
396        const IndexArray*   _indices;
397
398        const Drawable::Extensions * _extensions;
399};
400#endif
401
402
403Geometry::ArrayData::ArrayData(const ArrayData& data,const CopyOp& copyop):
404    array(copyop(data.array.get())),
405    indices(dynamic_cast<osg::IndexArray*>(copyop(data.indices.get()))),
406    binding(data.binding),
407    normalize(data.normalize)
408{
409}
410
411Geometry::Vec3ArrayData::Vec3ArrayData(const Vec3ArrayData& data,const CopyOp& copyop):
412    array(dynamic_cast<osg::Vec3Array*>(copyop(data.array.get()))),
413    indices(dynamic_cast<osg::IndexArray*>(copyop(data.indices.get()))),
414    binding(data.binding),
415    normalize(data.normalize)
416{
417}
418
419Geometry::Geometry()
420{
421    // temporary test
422    // setSupportsDisplayList(false);
423
424    _fastPath = false;
425    _fastPathHint = true;
426}
427
428Geometry::Geometry(const Geometry& geometry,const CopyOp& copyop):
429    Drawable(geometry,copyop),
430    _vertexData(geometry._vertexData,copyop),
431    _normalData(geometry._normalData,copyop),
432    _colorData(geometry._colorData,copyop),
433    _secondaryColorData(geometry._secondaryColorData,copyop),
434    _fogCoordData(geometry._fogCoordData,copyop),
435    _fastPath(geometry._fastPath),
436    _fastPathHint(geometry._fastPathHint)
437{
438    // temporary test
439    // setSupportsDisplayList(false);
440
441    for(PrimitiveSetList::const_iterator pitr=geometry._primitives.begin();
442        pitr!=geometry._primitives.end();
443        ++pitr)
444    {
445        PrimitiveSet* primitive = copyop(pitr->get());
446        if (primitive) _primitives.push_back(primitive);
447    }
448
449    for(ArrayDataList::const_iterator titr=geometry._texCoordList.begin();
450        titr!=geometry._texCoordList.end();
451        ++titr)
452    {
453        _texCoordList.push_back(ArrayData(*titr, copyop));
454    }
455
456    for(ArrayDataList::const_iterator vitr=geometry._vertexAttribList.begin();
457        vitr!=geometry._vertexAttribList.end();
458        ++vitr)
459    {
460        _vertexAttribList.push_back(ArrayData(*vitr, copyop));
461    }
462}
463
464Geometry::~Geometry()
465{
466    // do dirty here to keep the getGLObjectSizeHint() estimate on the ball
467    dirtyDisplayList();
468   
469    // no need to delete, all automatically handled by ref_ptr :-)
470}
471
472bool Geometry::empty() const
473{
474    if (!_primitives.empty()) return false;
475    if (!_vertexData.empty()) return false;
476    if (!_normalData.empty()) return false;
477    if (!_colorData.empty()) return false;
478    if (!_secondaryColorData.empty()) return false;
479    if (!_fogCoordData.empty()) return false;
480    if (!_texCoordList.empty()) return false;
481    if (!_vertexAttribList.empty()) return false;
482    return true;
483}
484
485void Geometry::setVertexArray(Array* array)
486{
487    _vertexData.array = array;
488    computeFastPathsUsed();
489    dirtyDisplayList();
490    dirtyBound();
491
492    if (_useVertexBufferObjects && array) addVertexBufferObjectIfRequired(array);
493}
494
495void Geometry::setVertexIndices(IndexArray* array)
496{
497    _vertexData.indices = array;
498    computeFastPathsUsed();
499    dirtyDisplayList();
500    dirtyBound();
501}
502
503void Geometry::setVertexData(const ArrayData& arrayData)
504{
505    _vertexData = arrayData;
506    computeFastPathsUsed();
507    dirtyDisplayList();
508    dirtyBound();
509
510    if (_useVertexBufferObjects && arrayData.array.valid()) addVertexBufferObjectIfRequired(arrayData.array.get());
511}
512
513void Geometry::setNormalArray(Array* array)
514{
515    _normalData.array = array;
516    if (!_normalData.array.valid()) _normalData.binding=BIND_OFF;
517    computeFastPathsUsed();
518    dirtyDisplayList();
519
520    if (_useVertexBufferObjects && array) addVertexBufferObjectIfRequired(array);
521}
522
523void Geometry::setNormalIndices(IndexArray* array)
524{
525    _normalData.indices = array;
526    computeFastPathsUsed();
527    dirtyDisplayList();
528}
529
530void Geometry::setNormalData(const ArrayData& arrayData)
531{
532    _normalData = arrayData; 
533    computeFastPathsUsed();
534    dirtyDisplayList();
535
536    if (_useVertexBufferObjects && arrayData.array.valid()) addVertexBufferObjectIfRequired(arrayData.array.get());
537}
538
539void Geometry::setColorArray(Array* array)
540{
541    _colorData.array = array;
542    if (!_colorData.array.valid()) _colorData.binding=BIND_OFF;
543    computeFastPathsUsed();
544    dirtyDisplayList();
545
546    if (_useVertexBufferObjects && array) addVertexBufferObjectIfRequired(array);
547}
548
549void Geometry::setColorIndices(IndexArray* array)
550{
551    _colorData.indices = array; 
552    computeFastPathsUsed();
553    dirtyDisplayList();
554}
555
556void Geometry::setColorData(const ArrayData& arrayData)
557{
558    _colorData = arrayData; 
559    computeFastPathsUsed();
560    dirtyDisplayList();
561
562    if (_useVertexBufferObjects && arrayData.array.valid()) addVertexBufferObjectIfRequired(arrayData.array.get());
563}
564
565
566void Geometry::setSecondaryColorArray(Array* array)
567{
568    _secondaryColorData.array = array;
569    if (!_secondaryColorData.array.valid()) _secondaryColorData.binding=BIND_OFF;
570    computeFastPathsUsed();
571    dirtyDisplayList();
572
573    if (_useVertexBufferObjects && array) addVertexBufferObjectIfRequired(array);
574}
575
576void Geometry::setSecondaryColorIndices(IndexArray* array)
577{
578    _secondaryColorData.indices = array;
579    computeFastPathsUsed();
580    dirtyDisplayList();
581}
582
583void Geometry::setSecondaryColorData(const ArrayData& arrayData)
584{
585    _secondaryColorData = arrayData;
586    computeFastPathsUsed();
587    dirtyDisplayList();
588
589    if (_useVertexBufferObjects && arrayData.array.valid()) addVertexBufferObjectIfRequired(arrayData.array.get());
590}
591
592void Geometry::setFogCoordArray(Array* array)
593{
594    _fogCoordData.array = array;
595    if (!_fogCoordData.array.valid()) _fogCoordData.binding=BIND_OFF;
596    computeFastPathsUsed();
597    dirtyDisplayList();
598
599    if (_useVertexBufferObjects && array) addVertexBufferObjectIfRequired(array);
600}
601
602void Geometry::setFogCoordIndices(IndexArray* array)
603{
604    _fogCoordData.indices = array;
605    computeFastPathsUsed();
606    dirtyDisplayList();
607}
608
609void Geometry::setFogCoordData(const ArrayData& arrayData)
610{
611    _fogCoordData = arrayData;
612    computeFastPathsUsed();
613    dirtyDisplayList();
614
615    if (_useVertexBufferObjects && arrayData.array.valid()) addVertexBufferObjectIfRequired(arrayData.array.get());
616}
617
618void Geometry::setNormalBinding(AttributeBinding ab)
619{
620    if (_normalData.binding == ab) return;
621   
622    _normalData.binding = ab;
623    computeFastPathsUsed();
624    dirtyDisplayList();
625}
626
627void Geometry::setColorBinding(AttributeBinding ab)
628{
629    if (_colorData.binding == ab) return;
630
631    _colorData.binding = ab;
632    computeFastPathsUsed();
633    dirtyDisplayList();
634}
635
636void Geometry::setSecondaryColorBinding(AttributeBinding ab)
637{
638    if (_secondaryColorData.binding == ab) return;
639
640    _secondaryColorData.binding = ab;
641    computeFastPathsUsed();
642    dirtyDisplayList();
643}
644
645void Geometry::setFogCoordBinding(AttributeBinding ab)
646{
647    if (_fogCoordData.binding == ab) return;
648
649    _fogCoordData.binding = ab;
650    computeFastPathsUsed();
651    dirtyDisplayList();
652}
653
654void Geometry::setTexCoordData(unsigned int unit,const ArrayData& arrayData)
655{
656    if (_texCoordList.size()<=unit)
657        _texCoordList.resize(unit+1);
658   
659    _texCoordList[unit] = arrayData;
660
661    if (_useVertexBufferObjects && arrayData.array.valid()) addVertexBufferObjectIfRequired(arrayData.array.get());
662}
663
664Geometry::ArrayData& Geometry::getTexCoordData(unsigned int unit)
665{
666    if (_texCoordList.size()<=unit)
667        _texCoordList.resize(unit+1);
668       
669    return _texCoordList[unit];
670}
671
672const Geometry::ArrayData& Geometry::getTexCoordData(unsigned int unit) const
673{
674    if (_texCoordList.size()<=unit)
675        return s_InvalidArrayData;
676       
677    return _texCoordList[unit];
678}
679
680void Geometry::setTexCoordArray(unsigned int unit,Array* array)
681{
682    getTexCoordData(unit).binding = BIND_PER_VERTEX;
683    getTexCoordData(unit).array = array;
684
685    computeFastPathsUsed();
686    dirtyDisplayList();
687
688    if (_useVertexBufferObjects && array)
689    {
690        addVertexBufferObjectIfRequired(array);
691    }
692}
693
694Array* Geometry::getTexCoordArray(unsigned int unit)
695{
696    if (unit<_texCoordList.size()) return _texCoordList[unit].array.get();
697    else return 0;
698}
699
700const Array* Geometry::getTexCoordArray(unsigned int unit) const
701{
702    if (unit<_texCoordList.size()) return _texCoordList[unit].array.get();
703    else return 0;
704}
705
706void Geometry::setTexCoordIndices(unsigned int unit,IndexArray* array)
707{
708    getTexCoordData(unit).indices = array;
709
710    computeFastPathsUsed();
711    dirtyDisplayList();
712}
713
714IndexArray* Geometry::getTexCoordIndices(unsigned int unit)
715{
716    if (unit<_texCoordList.size()) return _texCoordList[unit].indices.get();
717    else return 0;
718}
719
720const IndexArray* Geometry::getTexCoordIndices(unsigned int unit) const
721{
722    if (unit<_texCoordList.size()) return _texCoordList[unit].indices.get();
723    else return 0;
724}
725
726
727void Geometry::setVertexAttribData(unsigned int index, const Geometry::ArrayData& attrData)
728{
729    if (_vertexAttribList.size()<=index)
730        _vertexAttribList.resize(index+1);
731       
732    _vertexAttribList[index] = attrData;
733 
734    computeFastPathsUsed();
735    dirtyDisplayList();
736
737    if (_useVertexBufferObjects && attrData.array.valid()) addVertexBufferObjectIfRequired(attrData.array.get());
738}
739
740Geometry::ArrayData& Geometry::getVertexAttribData(unsigned int index)
741{
742    if (_vertexAttribList.size()<=index)
743        _vertexAttribList.resize(index+1);
744       
745    return _vertexAttribList[index];
746}
747
748const Geometry::ArrayData& Geometry::getVertexAttribData(unsigned int index) const
749{
750    if (_vertexAttribList.size()<=_vertexAttribList.size())
751        return s_InvalidArrayData;
752       
753    return _vertexAttribList[index];
754}
755
756void Geometry::setVertexAttribArray(unsigned int index, Array* array)
757{
758    getVertexAttribData(index).array = array;
759
760    computeFastPathsUsed();
761    dirtyDisplayList();
762
763    if (_useVertexBufferObjects && array) addVertexBufferObjectIfRequired(array);
764}
765
766Array *Geometry::getVertexAttribArray(unsigned int index)
767{
768    if (index<_vertexAttribList.size()) return _vertexAttribList[index].array.get();
769    else return 0;
770}
771
772const Array *Geometry::getVertexAttribArray(unsigned int index) const
773{
774    if (index<_vertexAttribList.size()) return _vertexAttribList[index].array.get();
775    else return 0;
776}
777
778void Geometry::setVertexAttribIndices(unsigned int index,IndexArray* array)
779{
780    getVertexAttribData(index).indices = array;
781
782    computeFastPathsUsed();
783    dirtyDisplayList();
784}
785
786IndexArray* Geometry::getVertexAttribIndices(unsigned int index)
787{
788    if (index<_vertexAttribList.size()) return _vertexAttribList[index].indices.get();
789    else return 0;
790}
791
792const IndexArray* Geometry::getVertexAttribIndices(unsigned int index) const
793{
794    if (index<_vertexAttribList.size()) return _vertexAttribList[index].indices.get();
795    else return 0;
796}
797
798void Geometry::setVertexAttribBinding(unsigned int index,AttributeBinding ab)
799{
800    if (getVertexAttribData(index).binding == ab)
801       return;
802    getVertexAttribData(index).binding = ab;
803    computeFastPathsUsed();
804    dirtyDisplayList();
805}
806
807Geometry::AttributeBinding Geometry::getVertexAttribBinding(unsigned int index) const
808{
809    if (index<_vertexAttribList.size()) return _vertexAttribList[index].binding;
810    else return BIND_OFF;
811}
812
813void Geometry::setVertexAttribNormalize(unsigned int index,GLboolean norm)
814{
815    getVertexAttribData(index).normalize = norm;
816
817    dirtyDisplayList();
818}
819
820GLboolean Geometry::getVertexAttribNormalize(unsigned int index) const
821{
822    if (index<_vertexAttribList.size()) return _vertexAttribList[index].normalize;
823    else return GL_FALSE;
824}
825
826bool Geometry::addPrimitiveSet(PrimitiveSet* primitiveset)
827{
828    if (primitiveset)
829    {
830        if (_useVertexBufferObjects) addElementBufferObjectIfRequired(primitiveset);
831
832        _primitives.push_back(primitiveset);
833        dirtyDisplayList();
834        dirtyBound();
835        return true;
836    }
837    notify(WARN)<<"Warning: invalid index i or primitiveset passed to osg::Geometry::addPrimitiveSet(i,primitiveset), ignoring call."<<std::endl;
838    return false;
839}
840
841bool Geometry::setPrimitiveSet(unsigned int i,PrimitiveSet* primitiveset)
842{
843    if (i<_primitives.size() && primitiveset)
844    {
845        if (_useVertexBufferObjects) addElementBufferObjectIfRequired(primitiveset);
846
847        _primitives[i] = primitiveset;
848        dirtyDisplayList();
849        dirtyBound();
850        return true;
851    }
852    notify(WARN)<<"Warning: invalid index i or primitiveset passed to osg::Geometry::setPrimitiveSet(i,primitiveset), ignoring call."<<std::endl;
853    return false;
854}
855
856bool Geometry::insertPrimitiveSet(unsigned int i,PrimitiveSet* primitiveset)
857{
858
859    if (primitiveset)
860    {
861        if (_useVertexBufferObjects) addElementBufferObjectIfRequired(primitiveset);
862
863        if (i<_primitives.size())
864        {
865            _primitives.insert(_primitives.begin()+i,primitiveset);
866            dirtyDisplayList();
867            dirtyBound();
868            return true;
869        }
870        else if (i==_primitives.size())
871        {
872            return addPrimitiveSet(primitiveset);
873        }
874       
875    }
876    notify(WARN)<<"Warning: invalid index i or primitiveset passed to osg::Geometry::insertPrimitiveSet(i,primitiveset), ignoring call."<<std::endl;
877    return false;
878}
879
880bool Geometry::removePrimitiveSet(unsigned int i, unsigned int numElementsToRemove)
881{
882    if (numElementsToRemove==0) return false;
883
884    if (i<_primitives.size())
885    {
886        if (i+numElementsToRemove<=_primitives.size())
887        {
888            _primitives.erase(_primitives.begin()+i,_primitives.begin()+i+numElementsToRemove);
889        }
890        else
891        {
892            // asking to delete too many elements, report a warning, and delete to
893            // the end of the primitive list.
894            notify(WARN)<<"Warning: osg::Geometry::removePrimitiveSet(i,numElementsToRemove) has been asked to remove more elements than are available,"<<std::endl;
895            notify(WARN)<<"         removing on from i to the end of the list of primitive sets."<<std::endl;
896            _primitives.erase(_primitives.begin()+i,_primitives.end());
897        }
898   
899        dirtyDisplayList();
900        dirtyBound();
901        return true;
902    }
903    notify(WARN)<<"Warning: invalid index i passed to osg::Geometry::removePrimitiveSet(i,numElementsToRemove), ignoring call."<<std::endl;
904    return false;
905}
906
907unsigned int Geometry::getPrimitiveSetIndex(const PrimitiveSet* primitiveset) const
908{
909    for (unsigned int primitiveSetIndex=0;primitiveSetIndex<_primitives.size();++primitiveSetIndex)
910    {
911        if (_primitives[primitiveSetIndex]==primitiveset) return primitiveSetIndex;
912    }
913    return _primitives.size(); // node not found.
914}
915
916bool Geometry::computeFastPathsUsed()
917{
918    static bool s_DisableFastPathInDisplayLists = getenv("OSG_DISABLE_FAST_PATH_IN_DISPLAY_LISTS")!=0;
919    if (_useDisplayList && s_DisableFastPathInDisplayLists)
920    {
921        osg::notify(osg::DEBUG_INFO)<<"Geometry::computeFastPathsUsed() - Disabling fast paths in display lists"<<std::endl;
922        _supportsVertexBufferObjects = _fastPath = false;
923        return _fastPath;
924    }
925
926    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
927    //
928    // check to see if fast path can be used.
929    //
930    _fastPath = true;
931    if (_vertexData.indices.valid()) _fastPath = false;
932    else if (_normalData.binding==BIND_PER_PRIMITIVE || (_normalData.binding==BIND_PER_VERTEX && _normalData.indices.valid())) _fastPath = false;
933    else if (_colorData.binding==BIND_PER_PRIMITIVE || (_colorData.binding==BIND_PER_VERTEX && _colorData.indices.valid())) _fastPath = false;
934    else if (_secondaryColorData.binding==BIND_PER_PRIMITIVE || (_secondaryColorData.binding==BIND_PER_VERTEX && _secondaryColorData.indices.valid())) _fastPath = false;
935    else if (_fogCoordData.binding==BIND_PER_PRIMITIVE || (_fogCoordData.binding==BIND_PER_VERTEX && _fogCoordData.indices.valid())) _fastPath = false;
936    else 
937    {
938        for( unsigned int va = 0; va < _vertexAttribList.size(); ++va )
939        {
940            if (_vertexAttribList[va].binding==BIND_PER_PRIMITIVE)
941            {
942                _fastPath = false;
943                break;
944            }
945            else
946            {
947                const Array * array = _vertexAttribList[va].array.get();
948                const IndexArray * idxArray = _vertexAttribList[va].indices.get();
949
950                if( _vertexAttribList[va].binding==BIND_PER_VERTEX &&
951                    array && array->getNumElements()>0 &&
952                    idxArray && idxArray->getNumElements()>0 )
953                {
954                    _fastPath = false;
955                    break;
956                }
957            }
958        }
959    }
960
961    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
962    //
963    // Set up tex coords if required.
964    //
965    for(unsigned int unit=0;unit<_texCoordList.size();++unit)
966    {
967        const ArrayData& texcoordData = _texCoordList[unit];
968        if (texcoordData.array.valid() && texcoordData.array->getNumElements()>0)
969        {
970            if (texcoordData.indices.valid())
971            {
972                if (texcoordData.indices->getNumElements()>0)
973                {
974                    _fastPath = false;         
975                    break;
976                }
977            }
978        }
979    }
980   
981    _supportsVertexBufferObjects = _fastPath;
982   
983    //_supportsVertexBufferObjects = false;
984    //_useVertexBufferObjects = false;
985
986    return _fastPath;
987}
988
989unsigned int Geometry::getGLObjectSizeHint() const
990{
991    unsigned int totalSize = 0;
992    if (_vertexData.array.valid()) totalSize += _vertexData.array->getTotalDataSize();
993
994    if (_normalData.array.valid()) totalSize += _normalData.array->getTotalDataSize();
995
996    if (_colorData.array.valid()) totalSize += _colorData.array->getTotalDataSize();
997
998    if (_secondaryColorData.array.valid()) totalSize += _secondaryColorData.array->getTotalDataSize();
999
1000    if (_fogCoordData.array.valid()) totalSize += _fogCoordData.array->getTotalDataSize();
1001
1002
1003    unsigned int unit;
1004    for(unit=0;unit<_texCoordList.size();++unit)
1005    {
1006        const Array* array = _texCoordList[unit].array.get();
1007        if (array) totalSize += array->getTotalDataSize();
1008
1009    }
1010
1011    bool handleVertexAttributes = true;
1012    if (handleVertexAttributes)
1013    {
1014        unsigned int index;
1015        for( index = 0; index < _vertexAttribList.size(); ++index )
1016        {
1017            const Array* array = _vertexAttribList[index].array.get();
1018            if (array) totalSize += array->getTotalDataSize();           
1019        }
1020    }
1021
1022    for(PrimitiveSetList::const_iterator itr=_primitives.begin();
1023        itr!=_primitives.end();
1024        ++itr)
1025    {
1026
1027        totalSize += 4*(*itr)->getNumIndices();
1028
1029    }
1030
1031
1032    // do a very simply mapping of display list size proportional to vertex datasize.
1033    return totalSize;
1034}
1035
1036bool Geometry::getArrayList(ArrayList& arrayList) const
1037{
1038    unsigned int startSize = arrayList.size();
1039   
1040    if (_vertexData.array.valid()) arrayList.push_back(_vertexData.array.get());
1041    if (_normalData.array.valid()) arrayList.push_back(_normalData.array.get());
1042    if (_colorData.array.valid()) arrayList.push_back(_colorData.array.get());
1043    if (_secondaryColorData.array.valid()) arrayList.push_back(_secondaryColorData.array.get());
1044    if (_fogCoordData.array.valid()) arrayList.push_back(_fogCoordData.array.get());
1045   
1046    for(unsigned int unit=0;unit<_texCoordList.size();++unit)
1047    {
1048        Array* array = _texCoordList[unit].array.get();
1049        if (array) arrayList.push_back(array);
1050    }
1051
1052    for(unsigned int  index = 0; index < _vertexAttribList.size(); ++index )
1053    {
1054        Array* array = _vertexAttribList[index].array.get();
1055        if (array) arrayList.push_back(array);
1056    }
1057
1058    return arrayList.size()!=startSize;
1059}
1060
1061bool Geometry::getDrawElementsList(DrawElementsList& drawElementsList) const
1062{
1063    unsigned int startSize = drawElementsList.size();
1064   
1065    for(PrimitiveSetList::const_iterator itr = _primitives.begin();
1066        itr != _primitives.end();
1067        ++itr)
1068    {
1069        osg::DrawElements* de = (*itr)->getDrawElements();
1070        if (de) drawElementsList.push_back(de);
1071    }
1072   
1073    return drawElementsList.size()!=startSize;
1074}
1075
1076void Geometry::addVertexBufferObjectIfRequired(osg::Array* array)
1077{
1078    if (_useVertexBufferObjects)
1079    {
1080        if (!array->getVertexBufferObject())
1081        {
1082            array->setVertexBufferObject(getOrCreateVertexBufferObject());
1083        }
1084    }
1085}
1086
1087void Geometry::addElementBufferObjectIfRequired(osg::PrimitiveSet* primitiveSet)
1088{
1089    if (_useVertexBufferObjects)
1090    {
1091        osg::DrawElements* drawElements = primitiveSet->getDrawElements();
1092        if (drawElements && !drawElements->getElementBufferObject())
1093        {
1094            drawElements->setElementBufferObject(getOrCreateElementBufferObject());
1095        }
1096    }
1097}
1098
1099osg::VertexBufferObject* Geometry::getOrCreateVertexBufferObject()
1100{
1101    ArrayList arrayList;
1102    getArrayList(arrayList);
1103
1104    ArrayList::iterator vitr;
1105    for(vitr = arrayList.begin();
1106        vitr != arrayList.end();
1107        ++vitr)
1108    {
1109        osg::Array* array = *vitr;
1110        if (array->getVertexBufferObject()) return array->getVertexBufferObject();
1111    }
1112
1113    return new osg::VertexBufferObject;
1114}
1115
1116osg::ElementBufferObject* Geometry::getOrCreateElementBufferObject()
1117{
1118    DrawElementsList drawElementsList;
1119    getDrawElementsList(drawElementsList);
1120
1121    DrawElementsList::iterator deitr;
1122    for(deitr = drawElementsList.begin();
1123        deitr != drawElementsList.end();
1124        ++deitr)
1125    {
1126        osg::DrawElements* elements = *deitr;
1127        if (elements->getElementBufferObject()) return elements->getElementBufferObject();
1128    }
1129
1130    return new osg::ElementBufferObject;
1131}
1132
1133void Geometry::setUseVertexBufferObjects(bool flag)
1134{
1135    // flag = true;
1136   
1137    // osg::notify(osg::NOTICE)<<"Geometry::setUseVertexBufferObjects("<<flag<<")"<<std::endl;
1138
1139    if (_useVertexBufferObjects==flag) return;
1140
1141    Drawable::setUseVertexBufferObjects(flag);
1142   
1143    ArrayList arrayList;
1144    getArrayList(arrayList);
1145
1146    DrawElementsList drawElementsList;
1147    getDrawElementsList(drawElementsList);
1148
1149    typedef std::vector<osg::VertexBufferObject*>  VertexBufferObjectList;
1150    typedef std::vector<osg::ElementBufferObject*>  ElementBufferObjectList;
1151
1152    if (_useVertexBufferObjects)
1153    {
1154        if (!arrayList.empty())
1155        {
1156
1157            VertexBufferObjectList vboList;
1158           
1159            osg::VertexBufferObject* vbo = 0;
1160
1161            ArrayList::iterator vitr;
1162            for(vitr = arrayList.begin();
1163                vitr != arrayList.end() && !vbo;
1164                ++vitr)
1165            {
1166                osg::Array* array = *vitr;
1167                if (array->getVertexBufferObject()) vbo = array->getVertexBufferObject();
1168            }
1169
1170            if (!vbo) vbo = new osg::VertexBufferObject;
1171
1172            for(vitr = arrayList.begin();
1173                vitr != arrayList.end();
1174                ++vitr)
1175            {
1176                osg::Array* array = *vitr;
1177                if (!array->getVertexBufferObject()) array->setVertexBufferObject(vbo);
1178            }
1179        }
1180
1181        if (!drawElementsList.empty())
1182        {
1183            ElementBufferObjectList eboList;
1184           
1185            osg::ElementBufferObject* ebo = 0;
1186
1187            DrawElementsList::iterator deitr;
1188            for(deitr = drawElementsList.begin();
1189                deitr != drawElementsList.end();
1190                ++deitr)
1191            {
1192                osg::DrawElements* elements = *deitr;
1193                if (elements->getElementBufferObject()) ebo = elements->getElementBufferObject();
1194            }
1195
1196            if (!ebo) ebo = new osg::ElementBufferObject;
1197
1198            for(deitr = drawElementsList.begin();
1199                deitr != drawElementsList.end();
1200                ++deitr)
1201            {
1202                osg::DrawElements* elements = *deitr;
1203                if (!elements->getElementBufferObject()) elements->setElementBufferObject(ebo);
1204            }
1205        }
1206    }
1207    else
1208    {
1209        for(ArrayList::iterator vitr = arrayList.begin();
1210            vitr != arrayList.end();
1211            ++vitr)
1212        {
1213            osg::Array* array = *vitr;
1214            if (array->getVertexBufferObject()) array->setVertexBufferObject(0);
1215        }
1216
1217        for(DrawElementsList::iterator deitr = drawElementsList.begin();
1218            deitr != drawElementsList.end();
1219            ++deitr)
1220        {
1221            osg::DrawElements* elements = *deitr;
1222            if (elements->getElementBufferObject()) elements->setElementBufferObject(0);
1223        }
1224    }
1225}
1226
1227void Geometry::dirtyDisplayList()
1228{
1229    Drawable::dirtyDisplayList();
1230}
1231
1232void Geometry::resizeGLObjectBuffers(unsigned int maxSize)
1233{
1234    Drawable::resizeGLObjectBuffers(maxSize);
1235
1236    ArrayList arrays;
1237    if (getArrayList(arrays))
1238    {
1239        for(ArrayList::iterator itr = arrays.begin();
1240            itr != arrays.end();
1241            ++itr)
1242        {
1243            (*itr)->resizeGLObjectBuffers(maxSize);
1244        }
1245    }
1246
1247    DrawElementsList drawElements;
1248    if (getDrawElementsList(drawElements))
1249    {
1250        for(DrawElementsList::iterator itr = drawElements.begin();
1251            itr != drawElements.end();
1252            ++itr)
1253        {
1254            (*itr)->resizeGLObjectBuffers(maxSize);
1255        }
1256    }
1257}
1258
1259void Geometry::releaseGLObjects(State* state) const
1260{
1261    Drawable::releaseGLObjects(state);
1262
1263    ArrayList arrays;
1264    if (getArrayList(arrays))
1265    {
1266        for(ArrayList::iterator itr = arrays.begin();
1267            itr != arrays.end();
1268            ++itr)
1269        {
1270            (*itr)->releaseGLObjects(state);
1271        }
1272    }
1273
1274    DrawElementsList drawElements;
1275    if (getDrawElementsList(drawElements))
1276    {
1277        for(DrawElementsList::iterator itr = drawElements.begin();
1278            itr != drawElements.end();
1279            ++itr)
1280        {
1281            (*itr)->releaseGLObjects(state);
1282        }
1283    }
1284
1285}
1286
1287#ifndef USE_OLD_DRAW_IMPLEMENTATOIN
1288void Geometry::drawImplementation(RenderInfo& renderInfo) const
1289{
1290    State& state = *renderInfo.getState();
1291    Drawable::Extensions* extensions = Drawable::getExtensions(state.getContextID(),true);
1292
1293    bool useFastPath = areFastPathsUsed();
1294    bool usingVertexBufferObjects = _useVertexBufferObjects && state.isVertexBufferObjectSupported();
1295    bool handleVertexAttributes = !_vertexAttribList.empty() && extensions->isVertexProgramSupported();
1296
1297    ArrayDispatchers& arrayDispatchers = state.getArrayDispatchers();
1298
1299    arrayDispatchers.setUseVertexAttribAlias(state.getUseVertexAttributeAliasing());
1300    arrayDispatchers.reset();
1301    // arrayDispatchers.setUseGLBeginEndAdapter(!useFastPath);
1302
1303    arrayDispatchers.activateNormalArray(_normalData.binding, _normalData.array.get(), _normalData.indices.get());
1304    arrayDispatchers.activateColorArray(_colorData.binding, _colorData.array.get(), _colorData.indices.get());
1305    arrayDispatchers.activateSecondaryColorArray(_secondaryColorData.binding, _secondaryColorData.array.get(), _secondaryColorData.indices.get());
1306    arrayDispatchers.activateFogCoordArray(_fogCoordData.binding, _fogCoordData.array.get(), _fogCoordData.indices.get());
1307
1308    if (handleVertexAttributes)
1309    {
1310        for(unsigned int unit=0;unit<_vertexAttribList.size();++unit)
1311        {
1312            arrayDispatchers.activateVertexAttribArray(_vertexAttribList[unit].binding, unit, _vertexAttribList[unit].array.get(), _vertexAttribList[unit].indices.get());
1313        }
1314    }
1315
1316    // dispatch any attributes that are bound overall
1317    arrayDispatchers.dispatch(BIND_OVERALL,0);
1318
1319    state.lazyDisablingOfVertexAttributes();
1320
1321    if (useFastPath)
1322    {
1323        // set up arrays
1324        if( _vertexData.array.valid() )
1325            state.setVertexPointer(_vertexData.array.get());
1326
1327        if (_normalData.binding==BIND_PER_VERTEX && _normalData.array.valid())
1328            state.setNormalPointer(_normalData.array.get());
1329
1330        if (_colorData.binding==BIND_PER_VERTEX && _colorData.array.valid())
1331            state.setColorPointer(_colorData.array.get());
1332
1333        if (_secondaryColorData.binding==BIND_PER_VERTEX && _secondaryColorData.array.valid())
1334            state.setSecondaryColorPointer(_secondaryColorData.array.get());
1335
1336        if (_fogCoordData.binding==BIND_PER_VERTEX && _fogCoordData.array.valid())
1337            state.setFogCoordPointer(_fogCoordData.array.get());
1338
1339        for(unsigned int unit=0;unit<_texCoordList.size();++unit)
1340        {
1341            const Array* array = _texCoordList[unit].array.get();
1342            if (array) state.setTexCoordPointer(unit,array);
1343        }
1344
1345        if( handleVertexAttributes )
1346        {
1347            for(unsigned int index = 0; index < _vertexAttribList.size(); ++index )
1348            {
1349                const Array* array = _vertexAttribList[index].array.get();
1350                const AttributeBinding ab = _vertexAttribList[index].binding;
1351                if( ab == BIND_PER_VERTEX && array )
1352                {
1353                    state.setVertexAttribPointer( index, array, _vertexAttribList[index].normalize );
1354                }
1355            }
1356        }
1357    }
1358    else
1359    {
1360        for(unsigned int unit=0;unit<_texCoordList.size();++unit)
1361        {
1362            arrayDispatchers.activateTexCoordArray(BIND_PER_VERTEX, unit, _texCoordList[unit].array.get(), _texCoordList[unit].indices.get());
1363        }
1364
1365        arrayDispatchers.activateVertexArray(BIND_PER_VERTEX, _vertexData.array.get(), _vertexData.indices.get());
1366    }
1367
1368    state.applyDisablingOfVertexAttributes();
1369
1370    bool bindPerPrimtiveSetActive = arrayDispatchers.active(BIND_PER_PRIMITIVE_SET);
1371    bool bindPerPrimtiveActive = arrayDispatchers.active(BIND_PER_PRIMITIVE);
1372
1373    unsigned int primitiveNum = 0;
1374
1375    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1376    //
1377    // draw the primitives themselves.
1378    //
1379    for(unsigned int primitiveSetNum=0; primitiveSetNum!=_primitives.size(); ++primitiveSetNum)
1380    {
1381
1382        // dispatch any attributes that are bound per primitive
1383        if (bindPerPrimtiveSetActive) arrayDispatchers.dispatch(BIND_PER_PRIMITIVE_SET, primitiveSetNum);
1384
1385        const PrimitiveSet* primitiveset = _primitives[primitiveSetNum].get();
1386
1387        if (useFastPath)
1388        {
1389            primitiveset->draw(state, usingVertexBufferObjects);
1390        }
1391        else
1392        {
1393            GLenum mode=primitiveset->getMode();
1394
1395            unsigned int primLength;
1396            switch(mode)
1397            {
1398                case(GL_POINTS):    primLength=1; break;
1399                case(GL_LINES):     primLength=2; break;
1400                case(GL_TRIANGLES): primLength=3; break;
1401                case(GL_QUADS):     primLength=4; break;
1402                default:            primLength=0; break; // compute later when =0.
1403            }
1404
1405            // draw primitives by the more flexible "slow" path,
1406            // sending OpenGL glBegin/glVertex.../glEnd().
1407            switch(primitiveset->getType())
1408            {
1409                case(PrimitiveSet::DrawArraysPrimitiveType):
1410                {
1411                    if (primLength==0) primLength=primitiveset->getNumIndices();
1412
1413                    const DrawArrays* drawArray = static_cast<const DrawArrays*>(primitiveset);
1414                    arrayDispatchers.Begin(mode);
1415
1416                    unsigned int primCount=0;
1417                    unsigned int indexEnd = drawArray->getFirst()+drawArray->getCount();
1418                    for(unsigned int vindex=drawArray->getFirst();
1419                        vindex<indexEnd;
1420                        ++vindex,++primCount)
1421                    {
1422                        if (bindPerPrimtiveActive && (primCount%primLength)==0)
1423                        {
1424                            arrayDispatchers.dispatch(BIND_PER_PRIMITIVE,++primitiveNum);
1425                        }
1426
1427                        arrayDispatchers.dispatch(BIND_PER_VERTEX, vindex);
1428                    }
1429
1430                    arrayDispatchers.End();
1431                    break;
1432                }
1433                case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
1434                {
1435                    const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
1436                    unsigned int vindex=drawArrayLengths->getFirst();
1437                    for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
1438                        primItr!=drawArrayLengths->end();
1439                        ++primItr)
1440                    {
1441                        unsigned int localPrimLength;
1442                        if (primLength==0) localPrimLength=*primItr;
1443                        else localPrimLength=primLength;
1444
1445                        arrayDispatchers.Begin(mode);
1446
1447                        for(GLsizei primCount=0;
1448                            primCount<*primItr;
1449                            ++vindex,++primCount)
1450                        {
1451                            if (bindPerPrimtiveActive && (primCount%localPrimLength)==0)
1452                            {
1453                                arrayDispatchers.dispatch(BIND_PER_PRIMITIVE, ++primitiveNum);
1454                            }
1455                            arrayDispatchers.dispatch(BIND_PER_VERTEX, vindex);
1456                        }
1457
1458                        arrayDispatchers.End();
1459
1460                    }
1461                    break;
1462                }
1463                case(PrimitiveSet::DrawElementsUBytePrimitiveType):
1464                {
1465                    if (primLength==0) primLength=primitiveset->getNumIndices();
1466
1467                    const DrawElementsUByte* drawElements = static_cast<const DrawElementsUByte*>(primitiveset);
1468                    arrayDispatchers.Begin(mode);
1469
1470                    unsigned int primCount=0;
1471                    for(DrawElementsUByte::const_iterator primItr=drawElements->begin();
1472                        primItr!=drawElements->end();
1473                        ++primCount,++primItr)
1474                    {
1475
1476                        if (bindPerPrimtiveActive && (primCount%primLength)==0)
1477                        {
1478                            arrayDispatchers.dispatch(BIND_PER_PRIMITIVE, ++primitiveNum);
1479                        }
1480
1481                        unsigned int vindex=*primItr;
1482                        arrayDispatchers.dispatch(BIND_PER_VERTEX, vindex);
1483                    }
1484
1485                    arrayDispatchers.End();
1486                    break;
1487                }
1488                case(PrimitiveSet::DrawElementsUShortPrimitiveType):
1489                {
1490                    if (primLength==0) primLength=primitiveset->getNumIndices();
1491
1492                    const DrawElementsUShort* drawElements = static_cast<const DrawElementsUShort*>(primitiveset);
1493                    arrayDispatchers.Begin(mode);
1494
1495                    unsigned int primCount=0;
1496                    for(DrawElementsUShort::const_iterator primItr=drawElements->begin();
1497                        primItr!=drawElements->end();
1498                        ++primCount,++primItr)
1499                    {
1500                        if (bindPerPrimtiveActive && (primCount%primLength)==0)
1501                        {
1502                            arrayDispatchers.dispatch(BIND_PER_PRIMITIVE, ++primitiveNum);
1503                        }
1504
1505                        unsigned int vindex=*primItr;
1506                        arrayDispatchers.dispatch(BIND_PER_VERTEX, vindex);
1507                    }
1508
1509                    arrayDispatchers.End();
1510                    break;
1511                }
1512                case(PrimitiveSet::DrawElementsUIntPrimitiveType):
1513                {
1514                    if (primLength==0) primLength=primitiveset->getNumIndices();
1515
1516                    const DrawElementsUInt* drawElements = static_cast<const DrawElementsUInt*>(primitiveset);
1517                    arrayDispatchers.Begin(mode);
1518
1519                    unsigned int primCount=0;
1520                    for(DrawElementsUInt::const_iterator primItr=drawElements->begin();
1521                        primItr!=drawElements->end();
1522                        ++primCount,++primItr)
1523                    {
1524                        if (bindPerPrimtiveActive && (primCount%primLength)==0)
1525                        {
1526                            arrayDispatchers.dispatch(BIND_PER_PRIMITIVE, ++primitiveNum);
1527                        }
1528
1529                        unsigned int vindex=*primItr;
1530                        arrayDispatchers.dispatch(BIND_PER_VERTEX, vindex);
1531                    }
1532
1533                    arrayDispatchers.End();
1534                    break;
1535                }
1536                default:
1537                {
1538                    break;
1539                }
1540            }
1541        }
1542    }
1543}
1544#else
1545void Geometry::drawImplementation(RenderInfo& renderInfo) const
1546{
1547    State& state = *renderInfo.getState();
1548    bool vertexAttribAlias = state.getUseVertexAttributeAliasing();
1549
1550
1551//    unsigned int contextID = state.getContextID();
1552   
1553    // osg::notify(osg::NOTICE)<<"Geometry::drawImplementation"<<std::endl;
1554
1555    if (_internalOptimizedGeometry.valid())
1556    {
1557        _internalOptimizedGeometry->drawImplementation(renderInfo);
1558        return;
1559    }
1560
1561    const Extensions* extensions = getExtensions(state.getContextID(),true);
1562
1563    if( !( ( _vertexData.array.valid() && _vertexData.array->getNumElements() != 0 ) ||
1564           ( _vertexAttribList.size() > 0 &&
1565             _vertexAttribList[0].array.valid() &&
1566             _vertexAttribList[0].array->getNumElements() != 0 ) ) )
1567    {
1568        return;
1569    }
1570
1571    if( ( _vertexData.indices.valid() && _vertexData.indices->getNumElements() == 0 ) ||
1572          ( _vertexAttribList.size() > 0 &&
1573          _vertexAttribList[0].indices.valid() &&
1574          _vertexAttribList[0].indices->getNumElements() == 0 ) )
1575    {
1576        return;
1577    }
1578
1579    AttributeBinding normalBinding = _normalData.binding;
1580    AttributeBinding colorBinding = _colorData.binding;
1581
1582    DrawNormal         drawNormal(vertexAttribAlias?0:_normalData.array.get(),vertexAttribAlias?0:_normalData.indices.get());
1583    DrawColor          drawColor(vertexAttribAlias?0:_colorData.array.get(),vertexAttribAlias?0:_colorData.indices.get());
1584    DrawSecondaryColor drawSecondaryColor(vertexAttribAlias?0:_secondaryColorData.array.get(),vertexAttribAlias?0:_secondaryColorData.indices.get(),extensions);
1585    DrawFogCoord       drawFogCoord(vertexAttribAlias?0:_fogCoordData.array.get(),vertexAttribAlias?0:_fogCoordData.indices.get(),extensions);
1586
1587
1588    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1589    //
1590    // Set up secondary color if required.
1591    //
1592    AttributeBinding secondaryColorBinding = _secondaryColorData.binding;
1593    if (secondaryColorBinding!=BIND_OFF && !extensions->isSecondaryColorSupported())
1594    {
1595        // switch off if not supported or have a valid data.
1596        secondaryColorBinding = BIND_OFF;
1597    }
1598
1599   
1600    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1601    //
1602    // Set up fog coord if required.
1603    //
1604    AttributeBinding fogCoordBinding = _fogCoordData.binding;
1605    if (fogCoordBinding!=BIND_OFF && !extensions->isFogCoordSupported())
1606    {
1607        // switch off if not supported or have a valid data.
1608        fogCoordBinding = BIND_OFF;
1609    }
1610
1611
1612
1613    unsigned int normalIndex = 0;
1614    unsigned int colorIndex = 0;
1615    unsigned int secondaryColorIndex = 0;
1616    unsigned int fogCoordIndex = 0;
1617
1618#if USE_DEFAULT_NORMAL
1619    // if no values are defined for normal and color provide some defaults...
1620    if (_normalData.binding==BIND_OFF) glNormal3f(0.0f,0.0f,1.0f);
1621#endif
1622
1623#if USE_DEFAULT_COLOUR
1624    if (_colorData.binding==BIND_OFF) glColor4f(1.0f,1.0f,1.0f,1.0f);
1625#endif
1626
1627    typedef std::vector< ref_ptr<DrawVertexAttrib> > DrawVertexAttribList;
1628    typedef std::map< Geometry::AttributeBinding, DrawVertexAttribList> DrawVertexAttribMap;
1629    DrawVertexAttribMap drawVertexAttribMap;
1630   
1631    bool vertexVertexAttributesSupported = extensions->isVertexProgramSupported();
1632    bool handleVertexAttributes = (vertexAttribAlias || !_vertexAttribList.empty()) && vertexVertexAttributesSupported;
1633
1634    bool usingVertexBufferObjects = _useVertexBufferObjects && state.isVertexBufferObjectSupported();
1635
1636
1637    if (vertexAttribAlias)
1638    {
1639        if (normalBinding!=BIND_OFF && normalBinding!=BIND_PER_VERTEX)
1640        {
1641            drawVertexAttribMap[normalBinding].push_back( new DrawVertexAttrib(extensions,2,false,_normalData.array.get(),_normalData.indices.get()) );
1642            normalBinding = BIND_OFF;
1643        }
1644
1645        if (colorBinding!=BIND_OFF && colorBinding!=BIND_PER_VERTEX)
1646        {
1647            drawVertexAttribMap[colorBinding].push_back( new DrawVertexAttrib(extensions,3,false,_colorData.array.get(),_colorData.indices.get()) );
1648            colorBinding = BIND_OFF;
1649        }
1650
1651        secondaryColorBinding = BIND_OFF;
1652        fogCoordBinding = BIND_OFF;
1653    }
1654
1655    // force the use of the slow path code to test the glBegin/glEnd replacement codes.
1656    bool forceSlowPath = true;
1657
1658    if (areFastPathsUsed() && !forceSlowPath)
1659    {
1660
1661#define USE_LAZY_DISABLING
1662
1663#ifdef USE_LAZY_DISABLING
1664        state.lazyDisablingOfVertexAttributes();
1665#endif
1666        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1667        //
1668        // fast path.       
1669        //
1670        if (usingVertexBufferObjects)
1671        {
1672            // osg::notify(osg::NOTICE)<<"Geometry::drawImplementation() Using VertexBufferObjects"<<std::endl;
1673
1674            if( _vertexData.array.valid() )
1675                state.setVertexPointer(_vertexData.array.get());
1676#ifndef USE_LAZY_DISABLING
1677            else
1678                state.disableVertexPointer();
1679#endif
1680
1681            if (_normalData.binding==BIND_PER_VERTEX && _normalData.array.valid())
1682                state.setNormalPointer(_normalData.array.get());
1683#ifndef USE_LAZY_DISABLING
1684            else
1685                state.disableNormalPointer();
1686#endif
1687
1688            if (_colorData.binding==BIND_PER_VERTEX && _colorData.array.valid())
1689                state.setColorPointer(_colorData.array.get());
1690#ifndef USE_LAZY_DISABLING
1691            else
1692                state.disableColorPointer();
1693#endif
1694
1695            if (secondaryColorBinding==BIND_PER_VERTEX && _secondaryColorData.array.valid())
1696                state.setSecondaryColorPointer(_secondaryColorData.array.get());
1697#ifndef USE_LAZY_DISABLING
1698            else
1699                state.disableSecondaryColorPointer();
1700#endif
1701
1702            if (fogCoordBinding==BIND_PER_VERTEX && _fogCoordData.array.valid())
1703                state.setFogCoordPointer(_fogCoordData.array.get());
1704#ifndef USE_LAZY_DISABLING
1705            else
1706                state.disableFogCoordPointer();
1707#endif
1708
1709            unsigned int unit;
1710            for(unit=0;unit<_texCoordList.size();++unit)
1711            {
1712                const Array* array = _texCoordList[unit].array.get();
1713                if (array)
1714                    state.setTexCoordPointer(unit,array);
1715#ifndef USE_LAZY_DISABLING
1716                else
1717                    state.disableTexCoordPointer(unit);
1718#endif
1719            }
1720#ifndef USE_LAZY_DISABLING
1721            state.disableTexCoordPointersAboveAndIncluding(unit);
1722#endif
1723
1724            if( handleVertexAttributes )
1725            {
1726                unsigned int index;
1727                for( index = 0; index < _vertexAttribList.size(); ++index )
1728                {
1729                    const Array* array = _vertexAttribList[index].array.get();
1730                    const AttributeBinding ab = _vertexAttribList[index].binding;
1731
1732                    if( ab == BIND_PER_VERTEX && array )
1733                    {
1734                        state.setVertexAttribPointer( index, array, _vertexAttribList[index].normalize );
1735                    }
1736                    else
1737                    {
1738                        if( array )
1739                        {
1740                            const IndexArray* indexArray = _vertexAttribList[index].indices.get();
1741
1742                            if( indexArray && indexArray->getNumElements() > 0 )
1743                            {
1744                                drawVertexAttribMap[ab].push_back(
1745                                    new DrawVertexAttrib(extensions,index,_vertexAttribList[index].normalize,array,indexArray) );
1746                            }
1747                            else
1748                            {
1749                                drawVertexAttribMap[ab].push_back(
1750                                    new DrawVertexAttrib(extensions,index,_vertexAttribList[index].normalize,array,0) );
1751                            }
1752                        }
1753
1754#ifndef USE_LAZY_DISABLING
1755                        state.disableVertexAttribPointer( index );
1756#endif
1757                    }
1758                }
1759#ifndef USE_LAZY_DISABLING
1760                state.disableVertexAttribPointersAboveAndIncluding( index );
1761#endif
1762            }
1763#ifndef USE_LAZY_DISABLING
1764            else if (vertexVertexAttributesSupported)
1765            {
1766                state.disableVertexAttribPointersAboveAndIncluding( 0 );
1767            }
1768#endif
1769        }
1770        else
1771        {
1772            // osg::notify(osg::NOTICE)<<"none VertexBuffer path"<<std::endl;
1773
1774            //
1775            // Non Vertex Buffer Object path for defining vertex arrays.
1776            //           
1777            if( _vertexData.array.valid() )
1778                state.setVertexPointer(_vertexData.array->getDataSize(),_vertexData.array->getDataType(),0,_vertexData.array->getDataPointer());
1779#ifndef USE_LAZY_DISABLING
1780            else
1781                state.disableVertexPointer();
1782#endif
1783
1784            if (_normalData.binding==BIND_PER_VERTEX && _normalData.array.valid())
1785                state.setNormalPointer(_normalData.array->getDataType(),0,_normalData.array->getDataPointer());
1786#ifndef USE_LAZY_DISABLING
1787            else
1788                state.disableNormalPointer();
1789#endif
1790
1791            if (_colorData.binding==BIND_PER_VERTEX && _colorData.array.valid())
1792                state.setColorPointer(_colorData.array->getDataSize(),_colorData.array->getDataType(),0,_colorData.array->getDataPointer());
1793#ifndef USE_LAZY_DISABLING
1794            else
1795                state.disableColorPointer();
1796#endif
1797
1798            if (secondaryColorBinding==BIND_PER_VERTEX && _secondaryColorData.array.valid())
1799                state.setSecondaryColorPointer(_secondaryColorData.array->getDataSize(),_secondaryColorData.array->getDataType(),0,_secondaryColorData.array->getDataPointer());
1800#ifndef USE_LAZY_DISABLING
1801            else
1802                state.disableSecondaryColorPointer();
1803#endif
1804
1805            if (fogCoordBinding==BIND_PER_VERTEX && _fogCoordData.array.valid())
1806                state.setFogCoordPointer(GL_FLOAT,0,_fogCoordData.array->getDataPointer());
1807#ifndef USE_LAZY_DISABLING
1808            else
1809                state.disableFogCoordPointer();
1810#endif
1811
1812            unsigned int unit;
1813            for(unit=0;unit<_texCoordList.size();++unit)
1814            {
1815                const Array* array = _texCoordList[unit].array.get();
1816                if (array)
1817                    state.setTexCoordPointer(unit,array->getDataSize(),array->getDataType(),0,array->getDataPointer());
1818#ifndef USE_LAZY_DISABLING
1819                else
1820                    state.disableTexCoordPointer(unit);
1821#endif
1822            }
1823#ifndef USE_LAZY_DISABLING
1824            state.disableTexCoordPointersAboveAndIncluding(unit);
1825#endif
1826
1827            if( handleVertexAttributes )
1828            {
1829                unsigned int index;
1830                for( index = 0; index < _vertexAttribList.size(); ++index )
1831                {
1832                    const Array* array = _vertexAttribList[index].array.get();
1833                    const AttributeBinding ab = _vertexAttribList[index].binding;
1834
1835                    if( ab == BIND_PER_VERTEX && array )
1836                    {
1837                        state.setVertexAttribPointer( index, array->getDataSize(), array->getDataType(),
1838                            _vertexAttribList[index].normalize, 0, array->getDataPointer() );
1839                    }
1840                    else
1841                    {
1842                        if( array )
1843                        {
1844                            const IndexArray* indexArray = _vertexAttribList[index].indices.get();
1845
1846                            if( indexArray && indexArray->getNumElements() > 0 )
1847                            {
1848                                drawVertexAttribMap[ab].push_back(
1849                                    new DrawVertexAttrib(extensions,index,_vertexAttribList[index].normalize,array,indexArray) );
1850                            }
1851                            else
1852                            {
1853                                drawVertexAttribMap[ab].push_back(
1854                                    new DrawVertexAttrib(extensions,index,_vertexAttribList[index].normalize,array,0) );
1855                            }
1856                        }
1857
1858#ifndef USE_LAZY_DISABLING
1859                        state.disableVertexAttribPointer( index );
1860#endif
1861                    }
1862                }
1863#ifndef USE_LAZY_DISABLING
1864                state.disableVertexAttribPointersAboveAndIncluding( index );
1865#endif
1866            }
1867#ifndef USE_LAZY_DISABLING
1868            else if (vertexVertexAttributesSupported)
1869            {
1870                state.disableVertexAttribPointersAboveAndIncluding( 0 );
1871            }
1872#endif
1873        }
1874
1875#ifdef USE_LAZY_DISABLING
1876        state.applyDisablingOfVertexAttributes();
1877#endif
1878
1879
1880        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1881        //
1882        // pass the overall binding values onto OpenGL.
1883        //
1884        if (normalBinding==BIND_OVERALL)        drawNormal(normalIndex++);
1885        if (colorBinding==BIND_OVERALL)         drawColor(colorIndex++);
1886        if (secondaryColorBinding==BIND_OVERALL)    drawSecondaryColor(secondaryColorIndex++);
1887        if (fogCoordBinding==BIND_OVERALL)          drawFogCoord(fogCoordIndex++);
1888        if (handleVertexAttributes)
1889        {
1890            DrawVertexAttribList &list = drawVertexAttribMap[BIND_OVERALL];
1891
1892            for( unsigned int i = 0; i < list.size(); ++i )
1893            {
1894                list[i]->applyAndIncrement();
1895            }
1896        }
1897
1898        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1899        //
1900        // draw the primitives themselves.
1901        //
1902        for(PrimitiveSetList::const_iterator itr=_primitives.begin();
1903            itr!=_primitives.end();
1904            ++itr)
1905        {
1906
1907            if (normalBinding==BIND_PER_PRIMITIVE_SET)      drawNormal(normalIndex++);
1908            if (colorBinding==BIND_PER_PRIMITIVE_SET)       drawColor(colorIndex++);
1909            if (secondaryColorBinding==BIND_PER_PRIMITIVE_SET)    drawSecondaryColor(secondaryColorIndex++);
1910            if (fogCoordBinding==BIND_PER_PRIMITIVE_SET)          drawFogCoord(fogCoordIndex++);
1911            if (handleVertexAttributes)
1912            {
1913                DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE_SET];
1914
1915                for( unsigned int i = 0; i < list.size(); ++i )
1916                {
1917                    list[i]->applyAndIncrement();
1918                }
1919            }
1920
1921            (*itr)->draw(state, usingVertexBufferObjects);
1922
1923        }
1924
1925        if (usingVertexBufferObjects)
1926        {
1927#if 1
1928            state.unbindVertexBufferObject();
1929            state.unbindElementBufferObject();
1930#endif
1931        }
1932
1933    }
1934    else
1935    {   
1936
1937        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1938        //
1939        // slow path.       
1940        //
1941       
1942
1943        typedef std::vector< ref_ptr<DrawMultiTexCoord> > DrawTexCoordList;
1944        DrawTexCoordList drawTexCoordList;
1945        drawTexCoordList.reserve(_texCoordList.size());
1946
1947        // fallback if multitexturing not supported.
1948        ref_ptr<DrawTexCoord> drawTextCoord;
1949
1950        if (extensions->isMultiTexSupported() && _texCoordList.size()>1)
1951        {
1952            // multitexture supported..
1953            for(unsigned int unit=0;unit!=_texCoordList.size();++unit)
1954            {
1955                const ArrayData& texcoordData = _texCoordList[unit];
1956                if (texcoordData.array.valid() && texcoordData.array->getNumElements()>0)
1957                {
1958                    if (texcoordData.indices.valid() && texcoordData.indices->getNumElements()>0)
1959                    {
1960                        drawTexCoordList.push_back(new DrawMultiTexCoord(GL_TEXTURE0+unit,texcoordData.array.get(),texcoordData.indices.get(),
1961                                                                         extensions));
1962                    }
1963                    else
1964                    {
1965                        drawTexCoordList.push_back(new DrawMultiTexCoord(GL_TEXTURE0+unit,texcoordData.array.get(),0,
1966                                                                          extensions));
1967                    }
1968                }
1969            }
1970        }
1971        else
1972        {
1973            if (!_texCoordList.empty())
1974            {
1975                const ArrayData& texcoordData = _texCoordList[0];
1976                if (texcoordData.array.valid() && texcoordData.array->getNumElements()>0)
1977                {
1978                    if (texcoordData.indices.valid())
1979                    {
1980                        if (texcoordData.indices->getNumElements()>0)
1981                        {
1982                            drawTextCoord = new DrawTexCoord(texcoordData.array.get(),texcoordData.indices.get());
1983                        }
1984                    }
1985                    else
1986                    {
1987                        drawTextCoord = new DrawTexCoord(texcoordData.array.get(),0);
1988                    }
1989                }
1990            }
1991        }
1992
1993        if(handleVertexAttributes)
1994        {
1995            unsigned int index;
1996            for( index = 1; index < _vertexAttribList.size(); ++index )
1997            {
1998                const ArrayData& vertAttribData = _vertexAttribList[index];
1999           
2000                if( vertAttribData.array.valid() && vertAttribData.array->getNumElements() > 0 )
2001                {
2002                    if( vertAttribData.indices.valid() && vertAttribData.indices->getNumElements() > 0 )
2003                    {
2004                        drawVertexAttribMap[vertAttribData.binding].push_back(
2005                            new DrawVertexAttrib(extensions,index,vertAttribData.normalize,vertAttribData.array.get(),vertAttribData.indices.get() ));
2006                    }
2007                    else
2008                    {
2009                        drawVertexAttribMap[vertAttribData.binding].push_back(
2010                            new DrawVertexAttrib(extensions,index,vertAttribData.normalize,vertAttribData.array.get(),0) );
2011                    }           
2012                }
2013            }
2014        }
2015
2016        // disable all the vertex arrays in the slow path as we are
2017        // sending everything using glVertex etc.
2018        state.disableAllVertexArrays();
2019
2020
2021        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2022        //
2023        // pass the overall binding values onto OpenGL.
2024        //
2025        if (_normalData.binding==BIND_OVERALL)      drawNormal(normalIndex++);
2026        if (_colorData.binding==BIND_OVERALL)       drawColor(colorIndex++);
2027        if (secondaryColorBinding==BIND_OVERALL)    drawSecondaryColor(secondaryColorIndex++);
2028        if (fogCoordBinding==BIND_OVERALL)          drawFogCoord(fogCoordIndex++);
2029        if (handleVertexAttributes)
2030        {
2031            DrawVertexAttribList &list = drawVertexAttribMap[BIND_OVERALL];
2032
2033            for( unsigned int i = 0; i < list.size(); ++i )
2034            {
2035                list[i]->applyAndIncrement();
2036            }
2037        }
2038
2039        // set up vertex functor.
2040        DrawVertex drawVertex(_vertexData.array.get(),_vertexData.indices.get());
2041
2042        bool useVertexAttrib =  _vertexAttribList.size() > 0 &&
2043                                _vertexAttribList[0].array.valid() &&
2044                                 _vertexAttribList[0].array->getNumElements()!=0;
2045
2046        ref_ptr<DrawVertexAttrib> drawVertexAttribZero;
2047        if( useVertexAttrib )
2048        {
2049            drawVertexAttribZero = new DrawVertexAttrib(extensions,0,
2050                _vertexAttribList[0].normalize,_vertexAttribList[0].array.get(),
2051                _vertexAttribList[0].indices.get());
2052        }
2053
2054        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2055        //
2056        // draw the primitives themselves.
2057        //
2058        for(PrimitiveSetList::const_iterator itr=_primitives.begin();
2059            itr!=_primitives.end();
2060            ++itr)
2061        {
2062            if (_normalData.binding==BIND_PER_PRIMITIVE_SET)           drawNormal(normalIndex++);
2063            if (_colorData.binding==BIND_PER_PRIMITIVE_SET)            drawColor(colorIndex++);
2064            if (secondaryColorBinding==BIND_PER_PRIMITIVE_SET)    drawSecondaryColor(secondaryColorIndex++);
2065            if (fogCoordBinding==BIND_PER_PRIMITIVE_SET)          drawFogCoord(fogCoordIndex++);
2066            if (handleVertexAttributes)
2067            {
2068                DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE_SET];
2069
2070                for( unsigned int i = 0; i < list.size(); ++i )
2071                {
2072                    list[i]->applyAndIncrement();
2073                }
2074            }
2075
2076            const PrimitiveSet* primitiveset = itr->get();
2077            GLenum mode=primitiveset->getMode();
2078
2079            unsigned int primLength;
2080            switch(mode)
2081            {
2082                case(GL_POINTS):    primLength=1; break;
2083                case(GL_LINES):     primLength=2; break;
2084                case(GL_TRIANGLES): primLength=3; break;
2085                case(GL_QUADS):     primLength=4; break;
2086                default:            primLength=0; break; // compute later when =0.
2087            }
2088
2089            // draw primitives by the more flexible "slow" path,
2090            // sending OpenGL glBegin/glVertex.../glEnd().
2091            switch(primitiveset->getType())
2092            {
2093                case(PrimitiveSet::DrawArraysPrimitiveType):
2094                {
2095                    if (primLength==0) primLength=primitiveset->getNumIndices();
2096
2097                    const DrawArrays* drawArray = static_cast<const DrawArrays*>(primitiveset);
2098                    glBegin(mode);
2099
2100                    unsigned int primCount=0;
2101                    unsigned int indexEnd = drawArray->getFirst()+drawArray->getCount();
2102                    for(unsigned int vindex=drawArray->getFirst();
2103                        vindex<indexEnd;
2104                        ++vindex,++primCount)
2105                    {
2106
2107                        if ((primCount%primLength)==0)
2108                        {
2109                            if (_normalData.binding==BIND_PER_PRIMITIVE)           drawNormal(normalIndex++);
2110                            if (_colorData.binding==BIND_PER_PRIMITIVE)            drawColor(colorIndex++);
2111                            if (secondaryColorBinding==BIND_PER_PRIMITIVE)    drawSecondaryColor(secondaryColorIndex++);
2112                            if (fogCoordBinding==BIND_PER_PRIMITIVE)          drawFogCoord(fogCoordIndex++);
2113                            if (handleVertexAttributes)
2114                            {
2115                                DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE];
2116
2117                                for( unsigned int i = 0; i < list.size(); ++i )
2118                                {
2119                                    list[i]->applyAndIncrement();
2120                                }
2121                            }                       
2122                        }
2123
2124                        if (_normalData.binding==BIND_PER_VERTEX)           drawNormal(vindex);
2125                        if (_colorData.binding==BIND_PER_VERTEX)            drawColor(vindex);
2126                        if (secondaryColorBinding==BIND_PER_VERTEX)    drawSecondaryColor(vindex);
2127                        if (fogCoordBinding==BIND_PER_VERTEX)          drawFogCoord(vindex);
2128                        if (handleVertexAttributes)
2129                        {
2130                            DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX];
2131
2132                            for( unsigned int i = 0; i < list.size(); ++i )
2133                            {
2134                                list[i]->applyAndIncrement();
2135                            }
2136                        } 
2137
2138                        for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin();
2139                            texItr!=drawTexCoordList.end();
2140                            ++texItr)
2141                        {
2142                            (*(*texItr))(vindex);
2143                        }
2144                        if (drawTextCoord.valid()) (*drawTextCoord)(vindex);
2145
2146                        if( useVertexAttrib )
2147                        {
2148                            (*drawVertexAttribZero)(vindex);
2149                        }
2150                        else
2151                        {
2152                            drawVertex(vindex);
2153                        }
2154                    }
2155                   
2156                    glEnd();
2157                    break;
2158                }
2159                case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
2160                {
2161
2162                    const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
2163                    unsigned int vindex=drawArrayLengths->getFirst();
2164                    for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
2165                        primItr!=drawArrayLengths->end();
2166                        ++primItr)
2167                    {
2168                        unsigned int localPrimLength;
2169                        if (primLength==0) localPrimLength=*primItr;
2170                        else localPrimLength=primLength;
2171
2172                        glBegin(mode);
2173
2174                        for(GLsizei primCount=0;primCount<*primItr;++primCount)
2175                        {
2176                            if ((primCount%localPrimLength)==0)
2177                            {
2178                                if (_normalData.binding==BIND_PER_PRIMITIVE)           drawNormal(normalIndex++);
2179                                if (_colorData.binding==BIND_PER_PRIMITIVE)            drawColor(colorIndex++);
2180                                if (secondaryColorBinding==BIND_PER_PRIMITIVE)    drawSecondaryColor(secondaryColorIndex++);
2181                                if (fogCoordBinding==BIND_PER_PRIMITIVE)          drawFogCoord(fogCoordIndex++);
2182                                if (handleVertexAttributes)
2183                                {
2184                                    DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE];
2185
2186                                    for( unsigned int i = 0; i < list.size(); ++i )
2187                                    {
2188                                        list[i]->applyAndIncrement();
2189                                    }
2190                                } 
2191                            }
2192                           
2193                            if (_normalData.binding==BIND_PER_VERTEX)           drawNormal(vindex);
2194                            if (_colorData.binding==BIND_PER_VERTEX)            drawColor(vindex);
2195                            if (secondaryColorBinding==BIND_PER_VERTEX)    drawSecondaryColor(vindex);
2196                            if (fogCoordBinding==BIND_PER_VERTEX)          drawFogCoord(vindex);
2197                            if (handleVertexAttributes)
2198                            {
2199                                DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX];
2200
2201                                for( unsigned int i = 0; i < list.size(); ++i )
2202                                {
2203                                    list[i]->applyAndIncrement();
2204                                }
2205                            } 
2206                            for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin();
2207                                texItr!=drawTexCoordList.end();
2208                                ++texItr)
2209                            {
2210                                (*(*texItr))(vindex);
2211                            }
2212                            if (drawTextCoord.valid()) (*drawTextCoord)(vindex);
2213
2214                            if( useVertexAttrib )
2215                            {
2216                                (*drawVertexAttribZero)(vindex);
2217                            }
2218                            else
2219                            {
2220                                drawVertex(vindex);
2221                            }
2222
2223                            ++vindex;
2224                        }
2225                       
2226                        glEnd();
2227
2228                    }
2229                    break;
2230                }
2231                case(PrimitiveSet::DrawElementsUBytePrimitiveType):
2232                {
2233                    if (primLength==0) primLength=primitiveset->getNumIndices();
2234
2235                    const DrawElementsUByte* drawElements = static_cast<const DrawElementsUByte*>(primitiveset);
2236                    glBegin(mode);
2237
2238                    unsigned int primCount=0;
2239                    for(DrawElementsUByte::const_iterator primItr=drawElements->begin();
2240                        primItr!=drawElements->end();
2241                        ++primCount,++primItr)
2242                    {
2243
2244                        if ((primCount%primLength)==0)
2245                        {
2246                            if (_normalData.binding==BIND_PER_PRIMITIVE)           drawNormal(normalIndex++);
2247                            if (_colorData.binding==BIND_PER_PRIMITIVE)            drawColor(colorIndex++);
2248                            if (secondaryColorBinding==BIND_PER_PRIMITIVE)    drawSecondaryColor(secondaryColorIndex++);
2249                            if (fogCoordBinding==BIND_PER_PRIMITIVE)          drawFogCoord(fogCoordIndex++);
2250                            if (handleVertexAttributes)
2251                            {
2252                                DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE];
2253
2254                                for( unsigned int i = 0; i < list.size(); ++i )
2255                                {
2256                                    list[i]->applyAndIncrement();
2257                                }
2258                            } 
2259                        }
2260                       
2261                        unsigned int vindex=*primItr;
2262
2263                        if (_normalData.binding==BIND_PER_VERTEX)           drawNormal(vindex);
2264                        if (_colorData.binding==BIND_PER_VERTEX)            drawColor(vindex);
2265                        if (secondaryColorBinding==BIND_PER_VERTEX)    drawSecondaryColor(vindex);
2266                        if (fogCoordBinding==BIND_PER_VERTEX)          drawFogCoord(vindex);
2267                        if ( extensions->isVertexProgramSupported() )
2268                        {
2269                            DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX];
2270
2271                            for( unsigned int i = 0; i < list.size(); ++i )
2272                            {
2273                                list[i]->applyAndIncrement();
2274                            }
2275                        } 
2276
2277                        for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin();
2278                            texItr!=drawTexCoordList.end();
2279                            ++texItr)
2280                        {
2281                            (*(*texItr))(vindex);
2282                        }
2283                        if (drawTextCoord.valid()) (*drawTextCoord)(vindex);
2284
2285                        if( useVertexAttrib )
2286                        {
2287                            (*drawVertexAttribZero)(vindex);
2288                        }
2289                        else
2290                        {
2291                            drawVertex(vindex);
2292                        }
2293                    }
2294
2295                    glEnd();
2296                    break;
2297                }
2298                case(PrimitiveSet::DrawElementsUShortPrimitiveType):
2299                {
2300                    if (primLength==0) primLength=primitiveset->getNumIndices();
2301
2302                    const DrawElementsUShort* drawElements = static_cast<const DrawElementsUShort*>(primitiveset);
2303                    glBegin(mode);
2304
2305                    unsigned int primCount=0;
2306                    for(DrawElementsUShort::const_iterator primItr=drawElements->begin();
2307                        primItr!=drawElements->end();
2308                        ++primCount,++primItr)
2309                    {
2310
2311                        if ((primCount%primLength)==0)
2312                        {
2313                            if (_normalData.binding==BIND_PER_PRIMITIVE)           drawNormal(normalIndex++);
2314                            if (_colorData.binding==BIND_PER_PRIMITIVE)            drawColor(colorIndex++);
2315                            if (secondaryColorBinding==BIND_PER_PRIMITIVE)    drawSecondaryColor(secondaryColorIndex++);
2316                            if (fogCoordBinding==BIND_PER_PRIMITIVE)          drawFogCoord(fogCoordIndex++);
2317                            if (handleVertexAttributes)
2318                            {
2319                                DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE];
2320
2321                                for( unsigned int i = 0; i < list.size(); ++i )
2322                                {
2323                                    list[i]->applyAndIncrement();
2324                                }
2325                            } 
2326                        }
2327                       
2328                        unsigned int vindex=*primItr;
2329
2330                        if (_normalData.binding==BIND_PER_VERTEX)           drawNormal(vindex);
2331                        if (_colorData.binding==BIND_PER_VERTEX)            drawColor(vindex);
2332                        if (secondaryColorBinding==BIND_PER_VERTEX)    drawSecondaryColor(vindex);
2333                        if (fogCoordBinding==BIND_PER_VERTEX)          drawFogCoord(vindex);
2334                        if (handleVertexAttributes)
2335                        {
2336                            DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX];
2337
2338                            for( unsigned int i = 0; i < list.size(); ++i )
2339                            {
2340                                list[i]->applyAndIncrement();
2341                            }
2342                        } 
2343
2344                        for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin();
2345                            texItr!=drawTexCoordList.end();
2346                            ++texItr)
2347                        {
2348                            (*(*texItr))(vindex);
2349                        }
2350                        if (drawTextCoord.valid()) (*drawTextCoord)(vindex);
2351
2352                        if( useVertexAttrib )
2353                        {
2354                            (*drawVertexAttribZero)(vindex);
2355                        }
2356                        else
2357                        {
2358                            drawVertex(vindex);
2359                        }
2360                    }
2361
2362                    glEnd();
2363                    break;
2364                }
2365                case(PrimitiveSet::DrawElementsUIntPrimitiveType):
2366                {
2367                    if (primLength==0) primLength=primitiveset->getNumIndices();
2368
2369                    const DrawElementsUInt* drawElements = static_cast<const DrawElementsUInt*>(primitiveset);
2370                    glBegin(mode);
2371
2372                    unsigned int primCount=0;
2373                    for(DrawElementsUInt::const_iterator primItr=drawElements->begin();
2374                        primItr!=drawElements->end();
2375                        ++primCount,++primItr)
2376                    {
2377
2378                        if ((primCount%primLength)==0)
2379                        {
2380                            if (_normalData.binding==BIND_PER_PRIMITIVE)           drawNormal(normalIndex++);
2381                            if (_colorData.binding==BIND_PER_PRIMITIVE)            drawColor(colorIndex++);
2382                            if (secondaryColorBinding==BIND_PER_PRIMITIVE)    drawSecondaryColor(secondaryColorIndex++);
2383                            if (fogCoordBinding==BIND_PER_PRIMITIVE)          drawFogCoord(fogCoordIndex++);
2384                            if ( extensions->isVertexProgramSupported() )
2385                            {
2386                                DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE];
2387
2388                                for( unsigned int i = 0; i < list.size(); ++i )
2389                                {
2390                                    list[i]->applyAndIncrement();
2391                                }
2392                            } 
2393                        }
2394                       
2395                        unsigned int vindex=*primItr;
2396
2397                        if (_normalData.binding==BIND_PER_VERTEX)           drawNormal(vindex);
2398                        if (_colorData.binding==BIND_PER_VERTEX)            drawColor(vindex);
2399                        if (secondaryColorBinding==BIND_PER_VERTEX)    drawSecondaryColor(vindex);
2400                        if (fogCoordBinding==BIND_PER_VERTEX)          drawFogCoord(vindex);
2401                        if ( extensions->isVertexProgramSupported() )
2402                        {
2403                            DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX];
2404
2405                            for( unsigned int i = 0; i < list.size(); ++i )
2406                            {
2407                                list[i]->applyAndIncrement();
2408                            }
2409                        } 
2410
2411                        for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin();
2412                            texItr!=drawTexCoordList.end();
2413                            ++texItr)
2414                        {
2415                            (*(*texItr))(vindex);
2416                        }
2417                        if (drawTextCoord.valid()) (*drawTextCoord)(vindex);
2418
2419                        if( useVertexAttrib )
2420                        {
2421                            (*drawVertexAttribZero)(vindex);
2422                        }
2423                        else
2424                        {
2425                            drawVertex(vindex);
2426                        }
2427                    }
2428
2429                    glEnd();
2430                    break;
2431                }
2432                default:
2433                {
2434                    break;
2435                }
2436            }
2437        }
2438    }
2439
2440}
2441#endif
2442
2443class AttributeFunctorArrayVisitor : public ArrayVisitor
2444{
2445    public:
2446   
2447        AttributeFunctorArrayVisitor(Drawable::AttributeFunctor& af):
2448            _af(af) {}
2449   
2450        virtual ~AttributeFunctorArrayVisitor() {}
2451
2452        virtual void apply(ByteArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2453        virtual void apply(ShortArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2454        virtual void apply(IntArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2455        virtual void apply(UByteArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2456        virtual void apply(UShortArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2457        virtual void apply(UIntArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2458        virtual void apply(Vec4ubArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2459        virtual void apply(FloatArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2460        virtual void apply(Vec2Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2461        virtual void apply(Vec3Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2462        virtual void apply(Vec4Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2463        virtual void apply(DoubleArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2464        virtual void apply(Vec2dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2465        virtual void apply(Vec3dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2466        virtual void apply(Vec4dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2467   
2468   
2469        inline void applyArray(Drawable::AttributeType type,Array* array)
2470        {
2471            if (array)
2472            {
2473                _type = type;
2474                array->accept(*this);
2475            }
2476        }
2477
2478    protected:       
2479       
2480        AttributeFunctorArrayVisitor& operator = (const AttributeFunctorArrayVisitor&) { return *this; }
2481        Drawable::AttributeFunctor&   _af;
2482        Drawable::AttributeType       _type;
2483};
2484
2485void Geometry::accept(AttributeFunctor& af)
2486{
2487    AttributeFunctorArrayVisitor afav(af);
2488
2489    if (_vertexData.array.valid())
2490    {
2491        afav.applyArray(VERTICES,_vertexData.array.get());
2492    }
2493    else if (_vertexAttribList.size()>0)
2494    {
2495        osg::notify(osg::INFO)<<"Geometry::accept(AttributeFunctor& af): Using vertex attribute instead"<<std::endl;
2496        afav.applyArray(VERTICES,_vertexAttribList[0].array.get());
2497    }
2498
2499    afav.applyArray(NORMALS,_normalData.array.get());
2500    afav.applyArray(COLORS,_colorData.array.get());
2501    afav.applyArray(SECONDARY_COLORS,_secondaryColorData.array.get());
2502    afav.applyArray(FOG_COORDS,_fogCoordData.array.get());
2503   
2504    for(unsigned unit=0;unit<_texCoordList.size();++unit)
2505    {
2506        afav.applyArray((AttributeType)(TEXTURE_COORDS_0+unit),_texCoordList[unit].array.get());
2507    }
2508
2509    for(unsigned int index=0; index<_vertexAttribList.size(); ++index)
2510    {
2511        afav.applyArray(index,_vertexAttribList[index].array.get());
2512    }
2513}
2514
2515class ConstAttributeFunctorArrayVisitor : public ConstArrayVisitor
2516{
2517    public:
2518   
2519        ConstAttributeFunctorArrayVisitor(Drawable::ConstAttributeFunctor& af):
2520            _af(af) {}
2521   
2522        virtual ~ConstAttributeFunctorArrayVisitor() {}
2523
2524        virtual void apply(const ByteArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2525        virtual void apply(const ShortArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2526        virtual void apply(const IntArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2527        virtual void apply(const UByteArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2528        virtual void apply(const UShortArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2529        virtual void apply(const UIntArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2530        virtual void apply(const Vec4ubArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2531        virtual void apply(const FloatArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2532        virtual void apply(const Vec2Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2533        virtual void apply(const Vec3Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2534        virtual void apply(const Vec4Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2535        virtual void apply(const DoubleArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2536        virtual void apply(const Vec2dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2537        virtual void apply(const Vec3dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2538        virtual void apply(const Vec4dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2539   
2540   
2541        inline void applyArray(Drawable::AttributeType type,const Array* array)
2542        {
2543            if (array)
2544            {
2545                _type = type;
2546                array->accept(*this);
2547            }
2548        }
2549   
2550protected:
2551
2552        ConstAttributeFunctorArrayVisitor& operator = (const ConstAttributeFunctorArrayVisitor&) { return *this; }
2553
2554        Drawable::ConstAttributeFunctor&    _af;
2555        Drawable::AttributeType             _type;
2556};
2557
2558void Geometry::accept(ConstAttributeFunctor& af) const
2559{
2560    ConstAttributeFunctorArrayVisitor afav(af);
2561   
2562    if (_vertexData.array.valid())
2563    {
2564        afav.applyArray(VERTICES,_vertexData.array.get());
2565    }
2566    else if (_vertexAttribList.size()>0)
2567    {
2568        osg::notify(osg::INFO)<<"Geometry::accept(ConstAttributeFunctor& af): Using vertex attribute instead"<<std::endl;
2569        afav.applyArray(VERTICES,_vertexAttribList[0].array.get());
2570    }
2571
2572    afav.applyArray(NORMALS,_normalData.array.get());
2573    afav.applyArray(COLORS,_colorData.array.get());
2574    afav.applyArray(SECONDARY_COLORS,_secondaryColorData.array.get());
2575    afav.applyArray(FOG_COORDS,_fogCoordData.array.get());
2576
2577    for(unsigned unit=0;unit<_texCoordList.size();++unit)
2578    {
2579        afav.applyArray((AttributeType)(TEXTURE_COORDS_0+unit),_texCoordList[unit].array.get());
2580    }
2581
2582    for(unsigned int index=0; index<_vertexAttribList.size(); ++index)
2583    {
2584        afav.applyArray(index,_vertexAttribList[index].array.get());
2585    }
2586}
2587
2588void Geometry::accept(PrimitiveFunctor& functor) const
2589{
2590    const osg::Array* vertices = _vertexData.array.get();
2591    const osg::IndexArray* indices = _vertexData.indices.get();
2592
2593    if (!vertices && _vertexAttribList.size()>0)
2594    {
2595        osg::notify(osg::INFO)<<"Using vertex attribute instead"<<std::endl;
2596        vertices = _vertexAttribList[0].array.get();
2597        indices = _vertexAttribList[0].indices.get();
2598    }
2599
2600    if (!vertices || vertices->getNumElements()==0) return;
2601
2602    if (!indices)
2603    {
2604        switch(vertices->getType())
2605        {
2606        case(Array::Vec2ArrayType):
2607            functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec2*>(vertices->getDataPointer()));
2608            break;
2609        case(Array::Vec3ArrayType):
2610            functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec3*>(vertices->getDataPointer()));
2611            break;
2612        case(Array::Vec4ArrayType):
2613            functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec4*>(vertices->getDataPointer()));
2614            break;
2615        case(Array::Vec2dArrayType):
2616            functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec2d*>(vertices->getDataPointer()));
2617            break;
2618        case(Array::Vec3dArrayType):
2619            functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec3d*>(vertices->getDataPointer()));
2620            break;
2621        case(Array::Vec4dArrayType):
2622            functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec4d*>(vertices->getDataPointer()));
2623            break;
2624        default:
2625            notify(WARN)<<"Warning: Geometry::accept(PrimitiveFunctor&) cannot handle Vertex Array type"<<vertices->getType()<<std::endl;
2626            return;
2627        }
2628       
2629        for(PrimitiveSetList::const_iterator itr=_primitives.begin();
2630            itr!=_primitives.end();
2631            ++itr)
2632        {
2633            (*itr)->accept(functor);
2634        }
2635    }
2636    else
2637    {
2638        const Vec2* vec2Array = 0;
2639        const Vec3* vec3Array = 0;
2640        const Vec4* vec4Array = 0;
2641        const Vec2d* vec2dArray = 0;
2642        const Vec3d* vec3dArray = 0;
2643        const Vec4d* vec4dArray = 0;
2644        Array::Type type = vertices->getType();
2645        switch(type)
2646        {
2647        case(Array::Vec2ArrayType):
2648            vec2Array = static_cast<const Vec2*>(vertices->getDataPointer());
2649            break;
2650        case(Array::Vec3ArrayType):
2651            vec3Array = static_cast<const Vec3*>(vertices->getDataPointer());
2652            break;
2653        case(Array::Vec4ArrayType):
2654            vec4Array = static_cast<const Vec4*>(vertices->getDataPointer());
2655            break;
2656        case(Array::Vec2dArrayType):
2657            vec2dArray = static_cast<const Vec2d*>(vertices->getDataPointer());
2658            break;
2659        case(Array::Vec3dArrayType):
2660            vec3dArray = static_cast<const Vec3d*>(vertices->getDataPointer());
2661            break;
2662        case(Array::Vec4dArrayType):
2663            vec4dArray = static_cast<const Vec4d*>(vertices->getDataPointer());
2664            break;
2665        default:
2666            notify(WARN)<<"Warning: Geometry::accept(PrimitiveFunctor&) cannot handle Vertex Array type"<<vertices->getType()<<std::endl;
2667            return;
2668        }
2669
2670        for(PrimitiveSetList::const_iterator itr=_primitives.begin();
2671            itr!=_primitives.end();
2672            ++itr)
2673        {
2674            const PrimitiveSet* primitiveset = itr->get();
2675            GLenum mode=primitiveset->getMode();
2676            switch(primitiveset->getType())
2677            {
2678                case(PrimitiveSet::DrawArraysPrimitiveType):
2679                {
2680                    const DrawArrays* drawArray = static_cast<const DrawArrays*>(primitiveset);
2681                    functor.begin(mode);
2682
2683                    unsigned int indexEnd = drawArray->getFirst()+drawArray->getCount();
2684                    for(unsigned int vindex=drawArray->getFirst();
2685                        vindex<indexEnd;
2686                        ++vindex)
2687                    {
2688                        switch(type)
2689                        {
2690                        case(Array::Vec2ArrayType):
2691                            functor.vertex(vec2Array[_vertexData.indices->index(vindex)]);
2692                            break;
2693                        case(Array::Vec3ArrayType):
2694                            functor.vertex(vec3Array[_vertexData.indices->index(vindex)]);
2695                            break;
2696                        case(Array::Vec4ArrayType):
2697                            functor.vertex(vec4Array[_vertexData.indices->index(vindex)]);
2698                            break;
2699                        case(Array::Vec2dArrayType):
2700                            functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]);
2701                            break;
2702                        case(Array::Vec3dArrayType):
2703                            functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]);
2704                            break;
2705                        case(Array::Vec4dArrayType):
2706                            functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]);
2707                            break;
2708                        default:
2709                            break;
2710                        }
2711
2712                    }
2713
2714                    functor.end();
2715                    break;
2716                }
2717                case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
2718                {
2719
2720                    const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
2721                    unsigned int vindex=drawArrayLengths->getFirst();
2722                    for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
2723                        primItr!=drawArrayLengths->end();
2724                        ++primItr)
2725                    {
2726
2727                        functor.begin(mode);
2728
2729                        for(GLsizei primCount=0;primCount<*primItr;++primCount)
2730                        {
2731                            switch(type)
2732                            {
2733                            case(Array::Vec2ArrayType):
2734                                functor.vertex(vec2Array[_vertexData.indices->index(vindex)]);
2735                                break;
2736                            case(Array::Vec3ArrayType):
2737                                functor.vertex(vec3Array[_vertexData.indices->index(vindex)]);
2738                                break;
2739                            case(Array::Vec4ArrayType):
2740                                functor.vertex(vec4Array[_vertexData.indices->index(vindex)]);
2741                                break;
2742                            case(Array::Vec2dArrayType):
2743                                functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]);
2744                                break;
2745                            case(Array::Vec3dArrayType):
2746                                functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]);
2747                                break;
2748                            case(Array::Vec4dArrayType):
2749                                functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]);
2750                                break;
2751                            default:
2752                                break;
2753                            }
2754                            ++vindex;
2755                        }
2756
2757                        functor.end();
2758
2759                    }
2760                    break;
2761                }
2762                case(PrimitiveSet::DrawElementsUBytePrimitiveType):
2763                {
2764                    const DrawElementsUByte* drawElements = static_cast<const DrawElementsUByte*>(primitiveset);
2765                    functor.begin(mode);
2766
2767                    unsigned int primCount=0;
2768                    for(DrawElementsUByte::const_iterator primItr=drawElements->begin();
2769                        primItr!=drawElements->end();
2770                        ++primCount,++primItr)
2771                    {
2772                        unsigned int vindex=*primItr;
2773                        switch(type)
2774                        {
2775                        case(Array::Vec2ArrayType):
2776                            functor.vertex(vec2Array[_vertexData.indices->index(vindex)]);
2777                            break;
2778                        case(Array::Vec3ArrayType):
2779                            functor.vertex(vec3Array[_vertexData.indices->index(vindex)]);
2780                            break;
2781                        case(Array::Vec4ArrayType):
2782                            functor.vertex(vec4Array[_vertexData.indices->index(vindex)]);
2783                            break;
2784                        case(Array::Vec2dArrayType):
2785                            functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]);
2786                            break;
2787                        case(Array::Vec3dArrayType):
2788                            functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]);
2789                            break;
2790                        case(Array::Vec4dArrayType):
2791                            functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]);
2792                            break;
2793                        default:
2794                            break;
2795                        }
2796                    }
2797
2798                    functor.end();
2799                    break;
2800                }
2801                case(PrimitiveSet::DrawElementsUShortPrimitiveType):
2802                {
2803                    const DrawElementsUShort* drawElements = static_cast<const DrawElementsUShort*>(primitiveset);
2804                    functor.begin(mode);
2805
2806                    for(DrawElementsUShort::const_iterator primItr=drawElements->begin();
2807                        primItr!=drawElements->end();
2808                        ++primItr)
2809                    {
2810                        unsigned int vindex=*primItr;
2811                        switch(type)
2812                        {
2813                        case(Array::Vec2ArrayType):
2814                            functor.vertex(vec2Array[_vertexData.indices->index(vindex)]);
2815                            break;
2816                        case(Array::Vec3ArrayType):
2817                            functor.vertex(vec3Array[_vertexData.indices->index(vindex)]);
2818                            break;
2819                        case(Array::Vec4ArrayType):
2820                            functor.vertex(vec4Array[_vertexData.indices->index(vindex)]);
2821                            break;
2822                        case(Array::Vec2dArrayType):
2823                            functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]);
2824                            break;
2825                        case(Array::Vec3dArrayType):
2826                            functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]);
2827                            break;
2828                        case(Array::Vec4dArrayType):
2829                            functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]);
2830                            break;
2831                        default:
2832                            break;
2833                        }
2834                    }
2835
2836                    functor.end();
2837                    break;
2838                }
2839                case(PrimitiveSet::DrawElementsUIntPrimitiveType):
2840                {
2841                    const DrawElementsUInt* drawElements = static_cast<const DrawElementsUInt*>(primitiveset);
2842                    functor.begin(mode);
2843
2844                    for(DrawElementsUInt::const_iterator primItr=drawElements->begin();
2845                        primItr!=drawElements->end();
2846                        ++primItr)
2847                    {
2848                        unsigned int vindex=*primItr;
2849                        switch(type)
2850                        {
2851                        case(Array::Vec2ArrayType):
2852                            functor.vertex(vec2Array[_vertexData.indices->index(vindex)]);
2853                            break;
2854                        case(Array::Vec3ArrayType):
2855                            functor.vertex(vec3Array[_vertexData.indices->index(vindex)]);
2856                            break;
2857                        case(Array::Vec4ArrayType):
2858                            functor.vertex(vec4Array[_vertexData.indices->index(vindex)]);
2859                            break;
2860                        case(Array::Vec2dArrayType):
2861                            functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]);
2862                            break;
2863                        case(Array::Vec3dArrayType):
2864                            functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]);
2865                            break;
2866                        case(Array::Vec4dArrayType):
2867                            functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]);
2868                            break;
2869                        default:
2870                            break;
2871                        }
2872                    }
2873
2874                    functor.end();
2875                    break;
2876                }
2877                default:
2878                {
2879                    break;
2880                }
2881            }
2882        }
2883    }
2884    return;
2885}
2886
2887void Geometry::accept(PrimitiveIndexFunctor& functor) const
2888{
2889    const osg::Array* vertices = _vertexData.array.get();
2890    const osg::IndexArray* indices = _vertexData.indices.get();
2891
2892    if (!vertices && _vertexAttribList.size()>0)
2893    {
2894        osg::notify(osg::INFO)<<"Geometry::accept(PrimitiveIndexFunctor& functor): Using vertex attribute instead"<<std::endl;
2895        vertices = _vertexAttribList[0].array.get();
2896        indices = _vertexAttribList[0].indices.get();
2897    }
2898
2899    if (!vertices || vertices->getNumElements()==0) return;
2900
2901    switch(vertices->getType())
2902    {
2903    case(Array::Vec2ArrayType):
2904        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec2*>(vertices->getDataPointer()));
2905        break;
2906    case(Array::Vec3ArrayType):
2907        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec3*>(vertices->getDataPointer()));
2908        break;
2909    case(Array::Vec4ArrayType):
2910        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec4*>(vertices->getDataPointer()));
2911        break;
2912    case(Array::Vec2dArrayType):
2913        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec2d*>(vertices->getDataPointer()));
2914        break;
2915    case(Array::Vec3dArrayType):
2916        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec3d*>(vertices->getDataPointer()));
2917        break;
2918    case(Array::Vec4dArrayType):
2919        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec4d*>(vertices->getDataPointer()));
2920        break;
2921    default:
2922        notify(WARN)<<"Warning: Geometry::accept(PrimitiveIndexFunctor&) cannot handle Vertex Array type"<<vertices->getType()<<std::endl;
2923        return;
2924    }
2925
2926    if (!_vertexData.indices.valid())
2927    {
2928        for(PrimitiveSetList::const_iterator itr=_primitives.begin();
2929            itr!=_primitives.end();
2930            ++itr)
2931        {
2932            (*itr)->accept(functor);
2933        }
2934    }
2935    else
2936    {
2937        for(PrimitiveSetList::const_iterator itr=_primitives.begin();
2938            itr!=_primitives.end();
2939            ++itr)
2940        {
2941            const PrimitiveSet* primitiveset = itr->get();
2942            GLenum mode=primitiveset->getMode();
2943            switch(primitiveset->getType())
2944            {
2945                case(PrimitiveSet::DrawArraysPrimitiveType):
2946                {
2947                    const DrawArrays* drawArray = static_cast<const DrawArrays*>(primitiveset);
2948                    functor.begin(mode);
2949
2950                    unsigned int indexEnd = drawArray->getFirst()+drawArray->getCount();
2951                    for(unsigned int vindex=drawArray->getFirst();
2952                        vindex<indexEnd;
2953                        ++vindex)
2954                    {
2955                        functor.vertex(_vertexData.indices->index(vindex));
2956                    }
2957                   
2958                    functor.end();
2959                    break;
2960                }
2961                case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
2962                {
2963
2964                    const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
2965                    unsigned int vindex=drawArrayLengths->getFirst();
2966                    for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
2967                        primItr!=drawArrayLengths->end();
2968                        ++primItr)
2969                    {
2970
2971                        functor.begin(mode);
2972
2973                        for(GLsizei primCount=0;primCount<*primItr;++primCount)
2974                        {
2975                            functor.vertex(_vertexData.indices->index(vindex));
2976                            ++vindex;
2977                        }
2978                       
2979                        functor.end();
2980
2981                    }
2982                    break;
2983                }
2984                case(PrimitiveSet::DrawElementsUBytePrimitiveType):
2985                {
2986                    const DrawElementsUByte* drawElements = static_cast<const DrawElementsUByte*>(primitiveset);
2987                    functor.begin(mode);
2988
2989                    unsigned int primCount=0;
2990                    for(DrawElementsUByte::const_iterator primItr=drawElements->begin();
2991                        primItr!=drawElements->end();
2992                        ++primCount,++primItr)
2993                    {
2994                        unsigned int vindex=*primItr;
2995                        functor.vertex(_vertexData.indices->index(vindex));
2996                    }
2997
2998                    functor.end();
2999                    break;
3000                }
3001                case(PrimitiveSet::DrawElementsUShortPrimitiveType):
3002                {
3003                    const DrawElementsUShort* drawElements = static_cast<const DrawElementsUShort*>(primitiveset);
3004                    functor.begin(mode);
3005
3006                    for(DrawElementsUShort::const_iterator primItr=drawElements->begin();
3007                        primItr!=drawElements->end();
3008                        ++primItr)
3009                    {
3010                        unsigned int vindex=*primItr;
3011                        functor.vertex(_vertexData.indices->index(vindex));
3012                    }
3013
3014                    functor.end();
3015                    break;
3016                }
3017                case(PrimitiveSet::DrawElementsUIntPrimitiveType):
3018                {
3019                    const DrawElementsUInt* drawElements = static_cast<const DrawElementsUInt*>(primitiveset);
3020                    functor.begin(mode);
3021
3022                    for(DrawElementsUInt::const_iterator primItr=drawElements->begin();
3023                        primItr!=drawElements->end();
3024                        ++primItr)
3025                    {
3026                        unsigned int vindex=*primItr;
3027                        functor.vertex(_vertexData.indices->index(vindex));
3028                    }
3029
3030                    functor.end();
3031                    break;
3032                }
3033                default:
3034                {
3035                    break;
3036                }
3037            }
3038        }
3039    }
3040    return;
3041}
3042
3043unsigned int _computeNumberOfPrimitives(const osg::Geometry& geom)
3044{
3045
3046    unsigned int totalNumberOfPrimitives = 0;
3047   
3048    for(Geometry::PrimitiveSetList::const_iterator itr=geom.getPrimitiveSetList().begin();
3049        itr!=geom.getPrimitiveSetList().end();
3050        ++itr)
3051    {
3052        const PrimitiveSet* primitiveset = itr->get();
3053        GLenum mode=primitiveset->getMode();
3054
3055        unsigned int primLength;
3056        switch(mode)
3057        {
3058            case(GL_POINTS):    primLength=1; osg::notify(osg::INFO)<<"prim=GL_POINTS"<<std::endl; break;
3059            case(GL_LINES):     primLength=2; osg::notify(osg::INFO)<<"prim=GL_LINES"<<std::endl; break;
3060            case(GL_TRIANGLES): primLength=3; osg::notify(osg::INFO)<<"prim=GL_TRIANGLES"<<std::endl; break;
3061            case(GL_QUADS):     primLength=4; osg::notify(osg::INFO)<<"prim=GL_QUADS"<<std::endl; break;
3062            default:            primLength=0; osg::notify(osg::INFO)<<"prim="<<std::hex<<mode<<std::dec<<std::endl; break; // compute later when =0.
3063        }
3064
3065        // draw primitives by the more flexible "slow" path,
3066        // sending OpenGL glBegin/glVertex.../glEnd().
3067        switch(primitiveset->getType())
3068        {
3069            case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
3070            {
3071
3072                const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
3073                for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
3074                    primItr!=drawArrayLengths->end();
3075                    ++primItr)
3076                {
3077                    if (primLength==0) totalNumberOfPrimitives += 1;
3078                    else totalNumberOfPrimitives += *primItr/primLength;
3079                }
3080                break;
3081            }
3082            default:
3083            {
3084                if (primLength==0) { totalNumberOfPrimitives += 1; osg::notify(osg::INFO)<<"   totalNumberOfPrimitives="<<totalNumberOfPrimitives<<std::endl;}
3085                else { totalNumberOfPrimitives += primitiveset->getNumIndices()/primLength; osg::notify(osg::INFO)<<"   primitiveset->getNumIndices()="<<primitiveset->getNumIndices()<<" totalNumberOfPrimitives="<<totalNumberOfPrimitives<<std::endl; }
3086
3087            }
3088        }
3089    }
3090
3091    return totalNumberOfPrimitives;
3092}
3093
3094template<class A>
3095bool _verifyBindings(const osg::Geometry& geom, const A& arrayData)
3096{
3097    unsigned int numElements = arrayData.indices.valid()?arrayData.indices->getNumElements():
3098                               arrayData.array.valid()?arrayData.array->getNumElements():0;
3099
3100    switch(arrayData.binding)
3101    {
3102        case(osg::Geometry::BIND_OFF):
3103            if (numElements>0) return false;
3104            break;
3105        case(osg::Geometry::BIND_OVERALL):
3106            if (numElements!=1) return false;
3107            break;
3108        case(osg::Geometry::BIND_PER_PRIMITIVE_SET):
3109            if (numElements!=geom.getPrimitiveSetList().size()) return false;
3110            break;
3111        case(osg::Geometry::BIND_PER_PRIMITIVE):
3112            if (numElements!=_computeNumberOfPrimitives(geom)) return false;
3113            break;
3114        case(osg::Geometry::BIND_PER_VERTEX):
3115        {
3116            unsigned int numVertices = geom.getVertexIndices()?geom.getVertexIndices()->getNumElements():
3117                                       geom.getVertexArray()?geom.getVertexArray()->getNumElements():0;
3118            if (numElements!=numVertices) return false;       
3119            break;
3120        }
3121    }
3122    return true;
3123}
3124
3125template<class A>
3126void _computeCorrectBindingsAndArraySizes(std::ostream& out, const osg::Geometry& geom, A& arrayData, const char* arrayName)
3127{
3128    unsigned int numElements = arrayData.indices.valid()?arrayData.indices->getNumElements():
3129                               arrayData.array.valid()?arrayData.array->getNumElements():0;
3130
3131    // check to see if binding matches 0 elements required.
3132    if (numElements==0)
3133    {
3134        // correct binding if not correct.
3135        if (arrayData.binding!=osg::Geometry::BIND_OFF)
3136        {
3137            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() "<<std::endl
3138                   <<"         "<<arrayName<<" binding has been reset to BIND_OFF"<<std::endl;
3139            arrayData.binding=osg::Geometry::BIND_OFF;
3140        }
3141        return;
3142    }
3143
3144    // check to see if binding matches 1 elements required.
3145    if (numElements==1)
3146    {
3147        // correct binding if not correct.
3148        if (arrayData.binding!=osg::Geometry::BIND_OVERALL)
3149        {
3150            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() "<<std::endl
3151                   <<"         "<<arrayName<<" binding has been reset to BIND_OVERALL"<<std::endl;
3152            arrayData.binding=osg::Geometry::BIND_OVERALL;
3153        }
3154        return;
3155    }
3156
3157
3158    unsigned int numVertices = geom.getVertexIndices()?geom.getVertexIndices()->getNumElements():
3159                               geom.getVertexArray()?geom.getVertexArray()->getNumElements():0;
3160   
3161    if ( numVertices==0 )
3162    {
3163        if (arrayData.binding!=osg::Geometry::BIND_OFF)
3164        {
3165            arrayData.array = 0;
3166            arrayData.indices = 0;
3167            arrayData.binding = osg::Geometry::BIND_OFF;
3168            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() vertex array is empty but "<<std::endl
3169                <<"         vertex array is empty but"<<arrayName<<" is set"<<std::endl
3170                <<"         reseting "<<arrayName<< " binding to BIND_OFF and array & indices to 0."<<std::endl;
3171        }
3172    }
3173   
3174    if (numElements==numVertices)
3175    {
3176        // correct the binding to per vertex.
3177        if (arrayData.binding!=osg::Geometry::BIND_PER_VERTEX)
3178        {
3179            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() "<<std::endl
3180                   <<"         "<<arrayName<<" binding has been reset to BIND_PER_VERTEX"<<std::endl;
3181            arrayData.binding = osg::Geometry::BIND_PER_VERTEX;
3182        }
3183        return;
3184    }
3185
3186
3187
3188    // check to see if binding might be per primitive set   
3189    unsigned int numPrimitiveSets = geom.getPrimitiveSetList().size();
3190   
3191    if (numElements==numPrimitiveSets)
3192    {
3193        if (arrayData.binding != osg::Geometry::BIND_PER_PRIMITIVE_SET)
3194        {
3195            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() "<<std::endl
3196                   <<"         "<<arrayName<<" binding has been reset to BIND_PER_PRIMITIVE_SET"<<std::endl;
3197            arrayData.binding = osg::Geometry::BIND_PER_PRIMITIVE_SET;
3198        }
3199        return;
3200    }
3201   
3202    // check to see if binding might be per primitive   
3203    unsigned int numPrimitives = _computeNumberOfPrimitives(geom);
3204    if (numElements==numPrimitives)
3205    {
3206        if (arrayData.binding != osg::Geometry::BIND_PER_PRIMITIVE)
3207        {
3208            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() "<<std::endl
3209                   <<"         "<<arrayName<<" binding has been reset to BIND_PER_PRIMITIVE"<<std::endl;
3210            arrayData.binding = osg::Geometry::BIND_PER_PRIMITIVE;
3211        }
3212        return;
3213    }
3214
3215    if (numElements>numVertices)
3216    {
3217        arrayData.binding = osg::Geometry::BIND_PER_VERTEX;
3218        return;
3219    }
3220    if (numElements>numPrimitives)
3221    {
3222        arrayData.binding = osg::Geometry::BIND_PER_PRIMITIVE;
3223        return;
3224    }
3225    if (numElements>numPrimitiveSets)
3226    {
3227        arrayData.binding = osg::Geometry::BIND_PER_PRIMITIVE_SET;
3228        return;
3229    }
3230    if (numElements>=1)
3231    {
3232        arrayData.binding = osg::Geometry::BIND_OVERALL;
3233        return;
3234    }
3235    arrayData.binding = osg::Geometry::BIND_OFF;
3236 
3237}       
3238
3239bool Geometry::verifyBindings(const ArrayData& arrayData) const
3240{
3241    return _verifyBindings(*this,arrayData);
3242}
3243
3244bool Geometry::verifyBindings(const Vec3ArrayData& arrayData) const
3245{
3246    return _verifyBindings(*this,arrayData);
3247}
3248
3249void Geometry::computeCorrectBindingsAndArraySizes(ArrayData& arrayData, const char* arrayName)
3250{
3251    _computeCorrectBindingsAndArraySizes(osg::notify(osg::INFO),*this,arrayData,arrayName);
3252}
3253
3254void Geometry::computeCorrectBindingsAndArraySizes(Vec3ArrayData& arrayData, const char* arrayName)
3255{
3256    _computeCorrectBindingsAndArraySizes(osg::notify(osg::INFO),*this,arrayData,arrayName);
3257}
3258
3259bool Geometry::verifyBindings() const
3260{
3261    if (!verifyBindings(_normalData)) return false;
3262    if (!verifyBindings(_colorData)) return false;
3263    if (!verifyBindings(_secondaryColorData)) return false;
3264    if (!verifyBindings(_fogCoordData)) return false;
3265
3266    for(ArrayDataList::const_iterator titr=_texCoordList.begin();
3267        titr!=_texCoordList.end();
3268        ++titr)
3269    {
3270        if (!verifyBindings(*titr)) return false;
3271    }
3272
3273    for(ArrayDataList::const_iterator vitr=_vertexAttribList.begin();
3274        vitr!=_vertexAttribList.end();
3275        ++vitr)
3276    {
3277        if (!verifyBindings(*vitr)) return false;
3278    }
3279
3280    return true;
3281}
3282
3283void Geometry::computeCorrectBindingsAndArraySizes()
3284{
3285    // if (verifyBindings()) return;
3286   
3287    computeCorrectBindingsAndArraySizes(_normalData,"_normalData");
3288    computeCorrectBindingsAndArraySizes(_colorData,"_colorData");
3289    computeCorrectBindingsAndArraySizes(_secondaryColorData,"_secondaryColorData");
3290    computeCorrectBindingsAndArraySizes(_fogCoordData,"_fogCoordData");
3291
3292    for(ArrayDataList::iterator titr=_texCoordList.begin();
3293        titr!=_texCoordList.end();
3294        ++titr)
3295    {
3296        computeCorrectBindingsAndArraySizes(*titr,"_texCoordList[]");
3297    }
3298
3299    for(ArrayDataList::iterator vitr=_vertexAttribList.begin();
3300        vitr!=_vertexAttribList.end();
3301        ++vitr)
3302    {
3303        computeCorrectBindingsAndArraySizes(*vitr,"_vertAttribList[]");
3304    }
3305}
3306
3307class ExpandIndexedArray : public osg::ConstArrayVisitor
3308{
3309    public:
3310        ExpandIndexedArray(const osg::IndexArray& indices,Array* targetArray):
3311            _indices(indices),
3312            _targetArray(targetArray) {}
3313       
3314        virtual ~ExpandIndexedArray() {}
3315
3316        // Create when both of the arrays are predefined templated classes. We
3317        // can do some optimizations in this case that aren't possible in the general
3318        // case.
3319        template <class T,class I>
3320        T* create_inline(const T& array,const I& indices)
3321        {
3322            T* newArray = 0;
3323
3324            // if source array type and target array type are equal but arrays arn't equal
3325            if (_targetArray && _targetArray->getType()==array.getType() && _targetArray!=(osg::Array*)(&array))
3326            {
3327                // reuse exisiting target array
3328                newArray = static_cast<T*>(_targetArray);
3329                if (newArray->size()!=indices.size())
3330                {
3331                    // make sure its the right size
3332                    newArray->resize(indices.size());
3333                }
3334            }
3335            else
3336            {
3337                //  else create a new array.
3338                newArray = new T(indices.size());
3339            }
3340
3341            for(unsigned int i=0;i<indices.size();++i)
3342            {
3343                (*newArray)[i]= array[indices[i]];
3344            }
3345
3346            return newArray;
3347        }
3348
3349        // Create when one of the arrays isn't one of the predefined templated classes. The
3350        // template parameter is the type of the array that will get created. This is  always
3351        // one of the predefined classes. We could call clone to get one of the same type as
3352        // the input array, but the interface of the osg::Array class doesn't include a way
3353        // to set an element.
3354        template <class T>
3355        osg::Array* create_noinline(const osg::Array& array, const osg::IndexArray& indices)
3356        {
3357            T* newArray = 0;
3358            typedef typename T::ElementDataType EDT;
3359
3360            unsigned int num_indices = indices.getNumElements();
3361            newArray = new T(num_indices);
3362
3363            const EDT* src = static_cast<const EDT*>(array.getDataPointer());
3364
3365            for(unsigned int i=0;i<num_indices;++i)
3366            {
3367                (*newArray)[i]= src[indices.index(i)];
3368            }
3369
3370            return newArray;
3371        }
3372
3373        osg::Array* create_noinline(const osg::Array& array, const osg::IndexArray& indices)
3374        {
3375            switch (array.getType())
3376            {
3377                case(osg::Array::ByteArrayType):   return create_noinline<osg::ByteArray>(array,indices);
3378                case(osg::Array::ShortArrayType):  return create_noinline<osg::ShortArray>(array,indices);
3379                case(osg::Array::IntArrayType):    return create_noinline<osg::IntArray>(array,indices);
3380                case(osg::Array::UByteArrayType):  return create_noinline<osg::UByteArray>(array,indices);
3381                case(osg::Array::UShortArrayType): return create_noinline<osg::UShortArray>(array,indices);
3382                case(osg::Array::UIntArrayType):   return create_noinline<osg::UIntArray>(array,indices);
3383                case(osg::Array::Vec4ubArrayType): return create_noinline<osg::Vec4ubArray>(array,indices);
3384                case(osg::Array::FloatArrayType):  return create_noinline<osg::FloatArray>(array,indices);
3385                case(osg::Array::Vec2ArrayType):   return create_noinline<osg::Vec2Array>(array,indices);
3386                case(osg::Array::Vec3ArrayType):   return create_noinline<osg::Vec3Array>(array,indices);
3387                case(osg::Array::Vec4ArrayType):   return create_noinline<osg::Vec4Array>(array,indices);
3388                case(osg::Array::Vec2dArrayType):   return create_noinline<osg::Vec2dArray>(array,indices);
3389                case(osg::Array::Vec3dArrayType):   return create_noinline<osg::Vec3dArray>(array,indices);
3390                case(osg::Array::Vec4dArrayType):   return create_noinline<osg::Vec4dArray>(array,indices);
3391                default:
3392                    return NULL;
3393            }
3394        }
3395
3396        template <class TA, class TI>
3397        osg::Array* create(const TA& array, const osg::IndexArray& indices)
3398        {
3399            // We know that indices.getType returned the same thing as TI, but
3400            // we need to determine whether it is really an instance of TI, or
3401            // perhaps another subclass of osg::Array that contains the same
3402            // type of data.
3403            const TI* ba(dynamic_cast<const TI*>(&indices));
3404            if (ba != NULL) {
3405                return create_inline(array,*ba);
3406            }
3407            else {
3408                return create_noinline(array, _indices);
3409            }
3410        }
3411
3412        template <class T>
3413        osg::Array* create(const T& array)
3414        {
3415            switch(_indices.getType())
3416            {
3417            case(osg::Array::ByteArrayType):   return create<T, osg::ByteArray>(array, _indices);
3418            case(osg::Array::ShortArrayType):  return create<T, osg::ShortArray>(array, _indices);
3419            case(osg::Array::IntArrayType):    return create<T, osg::IntArray>(array, _indices);
3420            case(osg::Array::UByteArrayType):  return create<T, osg::UByteArray>(array, _indices);
3421            case(osg::Array::UShortArrayType): return create<T, osg::UShortArray>(array, _indices);
3422            case(osg::Array::UIntArrayType):   return create<T, osg::UIntArray>(array, _indices);
3423            default:                           return create_noinline(array, _indices);
3424            }
3425           
3426        }
3427
3428        // applys for the predefined classes go through 1-arg create to do indexing
3429        virtual void apply(const osg::ByteArray& array) { _targetArray = create(array); }
3430        virtual void apply(const osg::ShortArray& array) { _targetArray = create(array); }
3431        virtual void apply(const osg::IntArray& array) { _targetArray = create(array); }
3432        virtual void apply(const osg::UByteArray& array) { _targetArray = create(array); }
3433        virtual void apply(const osg::UShortArray& array) { _targetArray = create(array); }
3434        virtual void apply(const osg::UIntArray& array) { _targetArray = create(array); }
3435        virtual void apply(const osg::Vec4ubArray& array) { _targetArray = create(array); }
3436        virtual void apply(const osg::FloatArray& array) { _targetArray = create(array); }
3437        virtual void apply(const osg::Vec2Array& array) { _targetArray = create(array); }
3438        virtual void apply(const osg::Vec3Array& array) { _targetArray = create(array); }
3439        virtual void apply(const osg::Vec4Array& array) { _targetArray = create(array); }
3440
3441        // other subclasses of osg::Array end up here
3442        virtual void apply(const osg::Array& array) { _targetArray = create_noinline(array, _indices); }
3443
3444        const osg::IndexArray& _indices;
3445        osg::Array* _targetArray;
3446
3447    protected:
3448
3449        ExpandIndexedArray& operator = (const ExpandIndexedArray&) { return *this; }
3450
3451};
3452
3453bool Geometry::suitableForOptimization() const
3454{
3455    bool hasIndices = false;
3456
3457    if (getVertexIndices()) hasIndices = true;
3458
3459    if (getNormalIndices()) hasIndices = true;
3460
3461    if (getColorIndices()) hasIndices = true;
3462
3463    if (getSecondaryColorIndices()) hasIndices = true;
3464
3465    if (getFogCoordIndices()) hasIndices = true;
3466
3467    for(unsigned int ti=0;ti<getNumTexCoordArrays();++ti)
3468    {
3469        if (getTexCoordIndices(ti)) hasIndices = true;
3470    }
3471   
3472    for(unsigned int vi=0;vi<getNumVertexAttribArrays();++vi)
3473    {
3474        if (getVertexAttribIndices(vi)) hasIndices = true;
3475    }
3476
3477    return hasIndices;
3478}
3479
3480void Geometry::copyToAndOptimize(Geometry& target)
3481{
3482    bool copyToSelf = (this==&target);
3483
3484    // copy over primitive sets.
3485    if (!copyToSelf) target.getPrimitiveSetList() = getPrimitiveSetList();
3486
3487    // copy over attribute arrays.
3488    if (getVertexIndices() && getVertexArray())
3489    {
3490        ExpandIndexedArray eia(*(getVertexIndices()),target.getVertexArray());
3491        getVertexArray()->accept(eia);
3492
3493        target.setVertexArray(eia._targetArray);
3494        target.setVertexIndices(0);
3495    }
3496    else if (getVertexArray())
3497    {
3498        if (!copyToSelf) target.setVertexArray(getVertexArray());
3499    }
3500
3501    target.setNormalBinding(getNormalBinding());
3502    if (getNormalIndices() && getNormalArray())
3503    {
3504        ExpandIndexedArray eia(*(getNormalIndices()),target.getNormalArray());
3505        getNormalArray()->accept(eia);
3506
3507        target.setNormalArray(dynamic_cast<osg::Vec3Array*>(eia._targetArray));
3508        target.setNormalIndices(0);
3509    }
3510    else if (getNormalArray())
3511    {
3512        if (!copyToSelf) target.setNormalArray(getNormalArray());
3513    }
3514
3515    target.setColorBinding(getColorBinding());
3516    if (getColorIndices() && getColorArray())
3517    {
3518        ExpandIndexedArray eia(*(getColorIndices()),target.getColorArray());
3519        getColorArray()->accept(eia);
3520
3521        target.setColorArray(eia._targetArray);
3522        target.setColorIndices(0);
3523    }
3524    else if (getColorArray())
3525    {
3526        if (!copyToSelf) target.setColorArray(getColorArray());
3527    }
3528
3529    target.setSecondaryColorBinding(getSecondaryColorBinding());
3530    if (getSecondaryColorIndices() && getSecondaryColorArray())
3531    {
3532        ExpandIndexedArray eia(*(getSecondaryColorIndices()),target.getSecondaryColorArray());
3533        getSecondaryColorArray()->accept(eia);
3534
3535        target.setSecondaryColorArray(eia._targetArray);
3536        target.setSecondaryColorIndices(0);
3537    }
3538    else if (getSecondaryColorArray())
3539    {
3540        if (!copyToSelf) target.setSecondaryColorArray(getSecondaryColorArray());
3541    }
3542
3543    target.setFogCoordBinding(getFogCoordBinding());
3544    if (getFogCoordIndices() && getFogCoordArray())
3545    {
3546        ExpandIndexedArray eia(*(getFogCoordIndices()),target.getFogCoordArray());
3547        getFogCoordArray()->accept(eia);
3548
3549        target.setFogCoordArray(eia._targetArray);
3550        target.setFogCoordIndices(0);
3551    }
3552    else if (getFogCoordArray())
3553    {
3554        if (!copyToSelf) target.setFogCoordArray(getFogCoordArray());
3555    }
3556
3557    for(unsigned int ti=0;ti<getNumTexCoordArrays();++ti)
3558    {
3559        if (getTexCoordIndices(ti) && getTexCoordArray(ti))
3560        {
3561            ExpandIndexedArray eia(*(getTexCoordIndices(ti)),target.getTexCoordArray(ti));
3562           
3563            getTexCoordArray(ti)->accept(eia);
3564
3565            target.setTexCoordArray(ti,eia._targetArray);
3566            target.setTexCoordIndices(ti,0);
3567        }
3568        else if (getTexCoordArray(ti))
3569        {
3570            if (!copyToSelf) target.setTexCoordArray(ti,getTexCoordArray(ti));
3571        }
3572    }
3573   
3574    for(unsigned int vi=0;vi<_vertexAttribList.size();++vi)
3575    {
3576        ArrayData& arrayData = _vertexAttribList[vi];
3577        if (arrayData.indices.valid())
3578        {
3579            ExpandIndexedArray eia(*arrayData.indices,target.getVertexAttribArray(vi));
3580            arrayData.array->accept(eia);
3581            target.setVertexAttribData(vi,ArrayData(eia._targetArray, 0, arrayData.binding, arrayData.normalize));
3582        }
3583        else if (arrayData.array.valid())
3584        {
3585            if (!copyToSelf) target.setVertexAttribData(vi,arrayData);
3586        }
3587    }
3588}
3589
3590bool Geometry::containsSharedArrays() const
3591{
3592    unsigned int numSharedArrays = 0;
3593   
3594    if (getVertexArray() && getVertexArray()->referenceCount()>1) ++numSharedArrays;
3595    if (getNormalArray() && getNormalArray()->referenceCount()>1) ++numSharedArrays;
3596    if (getColorArray() && getColorArray()->referenceCount()>1) ++numSharedArrays;
3597    if (getSecondaryColorArray() && getSecondaryColorArray()->referenceCount()>1) ++numSharedArrays;
3598    if (getFogCoordArray() && getFogCoordArray()->referenceCount()>1) ++numSharedArrays;
3599
3600    for(unsigned int ti=0;ti<getNumTexCoordArrays();++ti)
3601    {
3602        if (getTexCoordArray(ti) && getTexCoordArray(ti)->referenceCount()>1) ++numSharedArrays;
3603    }
3604   
3605    for(unsigned int vi=0;vi<_vertexAttribList.size();++vi)
3606    {
3607        const ArrayData& arrayData = _vertexAttribList[vi];
3608        if (arrayData.array.valid() && arrayData.array->referenceCount()>1) ++numSharedArrays;
3609    }
3610    return numSharedArrays!=0;
3611}
3612
3613void Geometry::duplicateSharedArrays()
3614{
3615    #define DUPLICATE_IF_REQUIRED(A) \
3616        if (get##A() && get##A()->referenceCount()>1) \
3617        { \
3618            set##A(dynamic_cast<osg::Array*>(get##A()->clone(osg::CopyOp::DEEP_COPY_ARRAYS))); \
3619        }
3620
3621    DUPLICATE_IF_REQUIRED(VertexArray)
3622    DUPLICATE_IF_REQUIRED(NormalArray)
3623    DUPLICATE_IF_REQUIRED(ColorArray)
3624    DUPLICATE_IF_REQUIRED(SecondaryColorArray)
3625    DUPLICATE_IF_REQUIRED(FogCoordArray)
3626
3627    for(unsigned int ti=0;ti<getNumTexCoordArrays();++ti)
3628    {
3629        if (getTexCoordArray(ti) && getTexCoordArray(ti)->referenceCount()>1)
3630        {
3631            setTexCoordArray(ti, dynamic_cast<osg::Array*>(getTexCoordArray(ti)->clone(osg::CopyOp::DEEP_COPY_ARRAYS)));
3632        }
3633    }
3634   
3635    for(unsigned int vi=0;vi<_vertexAttribList.size();++vi)
3636    {
3637        ArrayData& arrayData = _vertexAttribList[vi];
3638        if (arrayData.array.valid() && arrayData.array->referenceCount()>1)
3639        {
3640            arrayData.array = dynamic_cast<osg::Array*>(arrayData.array->clone(osg::CopyOp::DEEP_COPY_ARRAYS));
3641        }
3642    }
3643}
3644
3645void Geometry::computeInternalOptimizedGeometry()
3646{
3647    if (suitableForOptimization())
3648    {
3649        if (!_internalOptimizedGeometry) _internalOptimizedGeometry = new Geometry;
3650
3651        copyToAndOptimize(*_internalOptimizedGeometry);
3652    }
3653}
3654
3655
3656Geometry* osg::createTexturedQuadGeometry(const Vec3& corner,const Vec3& widthVec,const Vec3& heightVec, float l, float b, float r, float t)
3657{
3658    Geometry* geom = new Geometry;
3659
3660    Vec3Array* coords = new Vec3Array(4);
3661    (*coords)[0] = corner+heightVec;
3662    (*coords)[1] = corner;
3663    (*coords)[2] = corner+widthVec;
3664    (*coords)[3] = corner+widthVec+heightVec;
3665    geom->setVertexArray(coords);
3666
3667    Vec2Array* tcoords = new Vec2Array(4);
3668    (*tcoords)[0].set(l,t);
3669    (*tcoords)[1].set(l,b);
3670    (*tcoords)[2].set(r,b);
3671    (*tcoords)[3].set(r,t);
3672    geom->setTexCoordArray(0,tcoords);
3673
3674    osg::Vec4Array* colours = new osg::Vec4Array(1);
3675    (*colours)[0].set(1.0f,1.0f,1.0,1.0f);
3676    geom->setColorArray(colours);
3677    geom->setColorBinding(Geometry::BIND_OVERALL);
3678
3679    osg::Vec3Array* normals = new osg::Vec3Array(1);
3680    (*normals)[0] = widthVec^heightVec;
3681    (*normals)[0].normalize();
3682    geom->setNormalArray(normals);
3683    geom->setNormalBinding(Geometry::BIND_OVERALL);
3684
3685    geom->addPrimitiveSet(new DrawArrays(PrimitiveSet::QUADS,0,4));
3686   
3687    return geom;
3688}
3689
3690
3691
3692
3693///////////////////////////////////////////////////////////////////////////////////////////////
3694///////////////////////////////////////////////////////////////////////////////////////////////
3695///////////////////////////////////////////////////////////////////////////////////////////////
3696///////////////////////////////////////////////////////////////////////////////////////////////
3697///////////////////////////////////////////////////////////////////////////////////////////////
3698///////////////////////////////////////////////////////////////////////////////////////////////
3699///////////////////////////////////////////////////////////////////////////////////////////////
3700
3701
3702// experimental templated rendering code, please ignore...
3703// will move to osg::Geometry once complete.
3704// Robert Osfield, August 2003.
3705#if 0
3706
3707    struct DrawAttributeArrays
3708    {
3709        virtual bool valid() const = 0;
3710        virtual void set(osg::Geometry* geometry) = 0;
3711        virtual unsigned int draw(unsigned int index, unsigned int count) const = 0;
3712    };
3713
3714    struct V3
3715    {
3716        V3():_array(0) {}
3717
3718        bool valid() const { return _array!=0; }
3719
3720        void set(osg::Geometry* geometry)
3721        {
3722            _array = 0;
3723            osg::Array* array = geometry->getVertexArray();
3724            if (array && array->getType()==osg::Array::Vec3ArrayType)
3725            {
3726                osg::Vec3Array* vec3array = static_cast<osg::Vec3Array*>(array);
3727                if (!vec3array->empty()) _array = &(vec3array->front());
3728            }
3729        }
3730
3731        inline void draw(unsigned int index) const
3732        {
3733            glVertex3fv(_array[index].ptr());
3734        }
3735
3736        osg::Vec3* _array;
3737    };
3738
3739    struct V3USI
3740    {
3741        V3USI():_array(0),_indices(0) {}
3742
3743        bool valid() const { return _array!=0 && _indices!=0; }
3744
3745        void set(osg::Geometry* geometry)
3746        {
3747            _array = 0;
3748            osg::Array* array = geometry->getVertexArray();
3749            if (array && array->getType()==osg::Array::Vec3ArrayType)
3750            {
3751                osg::Vec3Array* vec3array = static_cast<osg::Vec3Array*>(array);
3752                if (!vec3array->empty()) _array = &(vec3array->front());
3753            }
3754
3755            _indices = 0;
3756            osg::IndexArray* indices = geometry->getVertexIndices();
3757            if (indices && indices->getType()==osg::Array::UShortArrayType)
3758            {
3759                osg::UShortArray* ushort3array = static_cast<osg::UShortArray*>(array);
3760                if (!ushort3array->empty()) _indices = &(ushort3array->front());
3761            }
3762        }
3763
3764        inline void draw(unsigned int index) const
3765        {
3766            glVertex3fv(_array[_indices[index]].ptr());
3767        }
3768
3769        osg::Vec3*      _array;
3770        unsigned short* _indices;
3771    };
3772
3773    //////////////////////////////
3774
3775    struct N3
3776    {
3777        N3():_array(0) {}
3778
3779        bool valid() const { return _array!=0; }
3780
3781        void set(osg::Geometry* geometry)
3782        {
3783            _array = 0;
3784            osg::Array* array = geometry->getVertexArray();
3785            if (array && array->getType()==osg::Array::Vec3ArrayType)
3786            {
3787                osg::Vec3Array* vec3array = static_cast<osg::Vec3Array*>(array);
3788                if (!vec3array->empty()) _array = &(vec3array->front());
3789            }
3790        }
3791
3792        inline void draw(unsigned int index) const
3793        {
3794            glNormal3fv(_array[index].ptr());
3795        }
3796
3797        osg::Vec3* _array;
3798    };
3799
3800    struct N3USI
3801    {
3802        N3USI():_array(0),_indices(0) {}
3803
3804        bool valid() const { return _array!=0 && _indices!=0; }
3805
3806        void set(osg::Geometry* geometry)
3807        {
3808            _array = 0;
3809            osg::Array* array = geometry->getVertexArray();
3810            if (array && array->getType()==osg::Array::Vec3ArrayType)
3811            {
3812                osg::Vec3Array* vec3array = static_cast<osg::Vec3Array*>(array);
3813                if (!vec3array->empty()) _array = &(vec3array->front());
3814            }
3815
3816            _indices = 0;
3817            osg::IndexArray* indices = geometry->getVertexIndices();
3818            if (indices && indices->getType()==osg::Array::UShortArrayType)
3819            {
3820                osg::UShortArray* ushortarray = static_cast<osg::UShortArray*>(array);
3821                if (!ushortarray->empty()) _indices = &(ushortarray->front());
3822            }
3823        }
3824
3825        inline void draw(unsigned int index) const
3826        {
3827            glNormal3fv(_array[_indices[index]].ptr());
3828        }
3829
3830        osg::Vec3*      _array;
3831        unsigned short* _indices;
3832    };
3833
3834    //////////////////////////////
3835
3836    struct C4
3837    {
3838        C4():_array(0) {}
3839
3840        bool valid() const { return _array!=0; }
3841
3842        void set(osg::Geometry* geometry)
3843        {
3844            _array = 0;
3845            osg::Array* array = geometry->getColorArray();
3846            if (array && array->getType()==osg::Array::Vec4ArrayType)
3847            {
3848                osg::Vec4Array* vec4array = static_cast<osg::Vec4Array*>(array);
3849                if (!vec4array->empty()) _array = &(vec4array->front());
3850            }
3851        }
3852
3853        inline void draw(unsigned int index) const
3854        {
3855            glVertex3fv(_array[index].ptr());
3856        }
3857
3858        osg::Vec4* _array;
3859    };
3860
3861    struct C4USI
3862    {
3863        C4USI():_array(0),_indices(0) {}
3864
3865        bool valid() const { return _array!=0 && _indices!=0; }
3866
3867        void set(osg::Geometry* geometry)
3868        {
3869            _array = 0;
3870            osg::Array* array = geometry->getColorArray();
3871            if (array && array->getType()==osg::Array::Vec4ArrayType)
3872            {
3873                osg::Vec4Array* vec4array = static_cast<osg::Vec4Array*>(array);
3874                if (!vec4array->empty()) _array = &(vec4array->front());
3875            }
3876
3877            _indices = 0;
3878            osg::IndexArray* indices = geometry->getColorIndices();
3879            if (indices && indices->getType()==osg::Array::UShortArrayType)
3880            {
3881                osg::UShortArray* ushortarray = static_cast<osg::UShortArray*>(array);
3882                if (!ushortarray->empty()) _indices = &(ushortarray->front());
3883            }
3884        }
3885
3886        inline void draw(unsigned int index) const
3887        {
3888            glColor4fv(_array[_indices[index]].ptr());
3889        }
3890
3891        osg::Vec4*      _array;
3892        unsigned short* _indices;
3893    };
3894
3895    //////////////////////////////
3896
3897    struct T2
3898    {
3899        T2():_array(0) {}
3900
3901        bool valid() const { return _array!=0; }
3902
3903        void set(osg::Geometry* geometry)
3904        {
3905            _array = 0;
3906            osg::Array* array = geometry->getTexCoordArray(0);
3907            if (array && array->getType()==osg::Array::Vec2ArrayType)
3908            {
3909                osg::Vec2Array* vec2array = static_cast<osg::Vec2Array*>(array);
3910                if (!vec2array->empty()) _array = &(vec2array->front());
3911            }
3912        }
3913
3914        inline void draw(unsigned int index) const
3915        {
3916            glTexCoord2fv(_array[index].ptr());
3917        }
3918
3919        osg::Vec2* _array;
3920    };
3921
3922    struct T2USI
3923    {
3924        T2USI():_array(0),_indices(0) {}
3925
3926        bool valid() const { return _array!=0 && _indices!=0; }
3927
3928        void set(osg::Geometry* geometry)
3929        {
3930            _array = 0;
3931            osg::Array* array = geometry->getTexCoordArray(0);
3932            if (array && array->getType()==osg::Array::Vec2ArrayType)
3933            {
3934                osg::Vec2Array* vec2array = static_cast<osg::Vec2Array*>(array);
3935                if (!vec2array->empty()) _array = &(vec2array->front());
3936            }
3937
3938            _indices = 0;
3939            osg::IndexArray* indices = geometry->getTexCoordIndices(0);
3940            if (indices && indices->getType()==osg::Array::UShortArrayType)
3941            {
3942                osg::UShortArray* ushortarray = static_cast<osg::UShortArray*>(array);
3943                if (!ushortarray->empty()) _indices = &(ushortarray->front());
3944            }
3945        }
3946
3947        inline void draw(unsigned int index) const
3948        {
3949            glTexCoord2fv(_array[_indices[index]].ptr());
3950        }
3951
3952        osg::Vec2*      _array;
3953        unsigned short* _indices;
3954    };
3955
3956
3957    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3958
3959    template < class T1 >
3960    struct DrawAttributeArrays_T : public DrawAttributeArrays
3961    {
3962        DrawAttributeArrays_T(osg::Geometry* geometry)
3963        {
3964
3965        }
3966
3967        virtual bool valid() const { return _t1.valid(); }
3968
3969        virtual void set(osg::Geometry* geometry)
3970        {
3971            _t1.set(geometry);
3972        }
3973
3974        virtual unsigned int draw(unsigned int index, unsigned int count) const
3975        {
3976            for(unsigned int i=0;i<count;++i,++index)
3977            {
3978                _t1.draw(index);
3979            }
3980            return index;
3981        }
3982
3983        T1 _t1;
3984    };
3985
3986    template < class T1, class T2 >
3987    struct DrawAttributeArrays_TT : public DrawAttributeArrays
3988    {
3989        DrawAttributeArrays_TT()
3990        {
3991        }
3992
3993        virtual bool valid() const { return _t1.valid() && _t2.valid(); }
3994
3995        virtual void set(osg::Geometry* geometry)
3996        {
3997            _t1.set(geometry);
3998            _t2.set(geometry);
3999        }
4000
4001        virtual unsigned int draw(unsigned int index, unsigned int count) const
4002        {
4003            for(unsigned int i=0;i<count;++i,++index)
4004            {
4005                _t1.draw(index);
4006                _t2.draw(index);
4007            }
4008            return index;
4009        }
4010
4011        T1 _t1;
4012        T1 _t2;
4013    };
4014
4015    template < class T1, class T2, class T3 >
4016    struct DrawAttributeArrays_TTT : public DrawAttributeArrays
4017    {
4018        DrawAttributeArrays_TTT()
4019        {
4020        }
4021
4022        virtual bool valid() const { return _t1.valid() && _t2.valid() && _t3.valid(); }
4023
4024        virtual void set(osg::Geometry* geometry)
4025        {
4026            _t1.set(geometry);
4027            _t2.set(geometry);
4028            _t3.set(geometry);
4029        }
4030
4031        virtual unsigned int draw(unsigned int index, unsigned int count) const
4032        {
4033            for(unsigned int i=0;i<count;++i,++index)
4034            {
4035                _t1.draw(index);
4036                _t2.draw(index);
4037                _t3.draw(index);
4038            }
4039            return index;
4040        }
4041
4042        T1 _t1;
4043        T2 _t2;
4044        T3 _t3;
4045    };
4046
4047    template < class T1, class T2, class T3, class T4 >
4048    struct DrawAttributeArrays_TTTT : public DrawAttributeArrays
4049    {
4050        DrawAttributeArrays_TTTT()
4051        {
4052        }
4053
4054        virtual bool valid() const { return _t1.valid() && _t2.valid() && _t3.valid() && _t4.valid(); }
4055
4056        virtual void set(osg::Geometry* geometry)
4057        {
4058            _t1.set(geometry);
4059            _t2.set(geometry);
4060            _t3.set(geometry);
4061            _t4.set(geometry);
4062        }
4063
4064        virtual unsigned int draw(unsigned int index, unsigned int count) const
4065        {
4066            for(unsigned int i=0;i<count;++i,++index)
4067            {
4068                _t1.draw(index);
4069                _t2.draw(index);
4070                _t3.draw(index);
4071                _t4.draw(index);
4072            }
4073            return index;
4074        }
4075
4076        T1 _t1;
4077        T2 _t2;
4078        T3 _t3;
4079        T4 _t4;
4080    };
4081
4082    template < class T1, class T2 >
4083    struct DrawAttributeArrays_TT_USI : public DrawAttributeArrays
4084    {
4085        DrawAttributeArrays_TT_USI()
4086        {
4087        }
4088
4089        virtual bool valid() const { return _t1.valid() && _t2.valid() && _indices!=0; }
4090
4091        virtual void set(osg::Geometry* geometry)
4092        {
4093            _t1.set(geometry);
4094            _t2.set(geometry);
4095
4096            _indices = 0;
4097            osg::IndexArray* indices = geometry->getVertexIndices();
4098            if (indices && indices->getType()==osg::Array::UShortArrayType)
4099            {
4100                osg::UShortArray* ushort3array = static_cast<osg::UShortArray*>(array);
4101                if (!ushort3array->empty()) _indices = &(ushort3array->front());
4102            }
4103        }
4104
4105        virtual unsigned int draw(unsigned int index, unsigned int count) const
4106        {
4107            for(unsigned int i=0;i<count;++i,++index)
4108            {
4109                unsigned int ivalue = _indices[index];
4110                _t1.draw(ivalue);
4111                _t2.draw(ivalue);
4112            }
4113            return index;
4114        }
4115
4116        T1 _t1;
4117        T2 _t2;
4118    };
4119
4120    template < class T1, class T2, class T3 >
4121    struct DrawAttributeArrays_TTT_USI : public DrawAttributeArrays
4122    {
4123        DrawAttributeArrays_TTT_USI()
4124        {
4125        }
4126
4127        virtual bool valid() const { return _t1.valid() && _t2.valid() && _t3.valid() && _indices!=0; }
4128
4129        virtual void set(osg::Geometry* geometry)
4130        {
4131            _t1.set(geometry);
4132            _t2.set(geometry);
4133            _t3.set(geometry);
4134
4135            _indices = 0;
4136            osg::IndexArray* indices = geometry->getVertexIndices();
4137            if (indices && indices->getType()==osg::Array::UShortArrayType)
4138            {
4139                osg::UShortArray* ushort3array = static_cast<osg::UShortArray*>(array);
4140                if (!ushort3array->empty()) _indices = &(ushort3array->front());
4141            }
4142        }
4143
4144        virtual unsigned int draw(unsigned int index, unsigned int count) const
4145        {
4146            for(unsigned int i=0;i<count;++i,++index)
4147            {
4148                unsigned int ivalue = _indices[index];
4149                _t1.draw(ivalue);
4150                _t2.draw(ivalue);
4151                _t3.draw(ivalue);
4152            }
4153            return index;
4154        }
4155
4156        T1 _t1;
4157        T2 _t2;
4158        T3 _t3;
4159    };
4160
4161    template < class T1, class T2, class T3, class T4 >
4162    struct DrawAttributeArrays_TTTT_USI : public DrawAttributeArrays
4163    {
4164        DrawAttributeArrays_TTTT_USI()
4165        {
4166        }
4167
4168        virtual bool valid() const { return _t1.valid() && _t2.valid() && _t3.valid() && _t4.valid() && _indices!=0; }
4169
4170        virtual void set(osg::Geometry* geometry)
4171        {
4172            _t1.set(geometry);
4173            _t2.set(geometry);
4174            _t3.set(geometry);
4175            _t4.set(geometry);
4176
4177            _indices = 0;
4178            osg::IndexArray* indices = geometry->getVertexIndices();
4179            if (indices && indices->getType()==osg::Array::UShortArrayType)
4180            {
4181                osg::UShortArray* ushort3array = static_cast<osg::UShortArray*>(array);
4182                if (!ushort3array->empty()) _indices = &(ushort3array->front());
4183            }
4184        }
4185
4186        virtual unsigned int draw(unsigned int index, unsigned int count) const
4187        {
4188            for(unsigned int i=0;i<count;++i,++index)
4189            {
4190                unsigned int ivalue = _indices[index];
4191                _t1.draw(ivalue);
4192                _t2.draw(ivalue);
4193                _t3.draw(ivalue);
4194                _t4.draw(ivalue);
4195            }
4196            return index;
4197        }
4198
4199        T1 _t1;
4200        T2 _t2;
4201        T3 _t3;
4202        T4 _t4;
4203    };
4204
4205    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4206
4207
4208    // One attribute x 2
4209
4210    typedef DrawAttributeArrays_T<V3>                    DrawAttributeArrays_V3;
4211    typedef DrawAttributeArrays_T<V3USI>                 DrawAttributeArrays_V3i;
4212
4213    // Two attributes x 15
4214
4215    typedef DrawAttributeArrays_TT<N3,V3>                DrawAttributeArrays_N3V3;
4216    typedef DrawAttributeArrays_TT<N3USI,V3>             DrawAttributeArrays_N3iV3;
4217    typedef DrawAttributeArrays_TT<N3,V3USI>             DrawAttributeArrays_N3V3i;
4218    typedef DrawAttributeArrays_TT<N3USI,V3USI>          DrawAttributeArrays_N3iV3i;
4219
4220    typedef DrawAttributeArrays_TT_USI<N3,V3>            DrawAttributeArrays_N3V3_i;
4221
4222    typedef DrawAttributeArrays_TT<C4,V3>                DrawAttributeArrays_C4V3;
4223    typedef DrawAttributeArrays_TT<C4USI,V3>             DrawAttributeArrays_C4iV3;
4224    typedef DrawAttributeArrays_TT<C4,V3USI>             DrawAttributeArrays_C4V3i;
4225    typedef DrawAttributeArrays_TT<C4USI,V3USI>          DrawAttributeArrays_C4iV3i;
4226
4227    typedef DrawAttributeArrays_TT_USI<C4,V3>            DrawAttributeArrays_C4V3_i;
4228
4229    typedef DrawAttributeArrays_TT<T2,V3>                DrawAttributeArrays_T2V3;
4230    typedef DrawAttributeArrays_TT<T2USI,V3>             DrawAttributeArrays_T2iV3;
4231    typedef DrawAttributeArrays_TT<T2,V3USI>             DrawAttributeArrays_T2V3i;
4232    typedef DrawAttributeArrays_TT<T2USI,V3USI>          DrawAttributeArrays_T2iV3i;
4233
4234    typedef DrawAttributeArrays_TT_USI<T2,V3>            DrawAttributeArrays_T2V3_i;
4235
4236    // Three attributes x 27
4237
4238    typedef DrawAttributeArrays_TTT<C4,N3,V3>            DrawAttributeArrays_C4N3V3;
4239    typedef DrawAttributeArrays_TTT<C4USI,N3,V3>         DrawAttributeArrays_C4iN3V3;
4240    typedef DrawAttributeArrays_TTT<C4,N3USI,V3>         DrawAttributeArrays_C4N3iV3;
4241    typedef DrawAttributeArrays_TTT<C4USI,N3USI,V3>      DrawAttributeArrays_C4iN3iV3;
4242
4243    typedef DrawAttributeArrays_TTT<C4,N3,V3USI>         DrawAttributeArrays_C4N3V3i;
4244    typedef DrawAttributeArrays_TTT<C4USI,N3,V3USI>      DrawAttributeArrays_C4iN3V3i;
4245    typedef DrawAttributeArrays_TTT<C4,N3USI,V3USI>      DrawAttributeArrays_C4N3iV3i;
4246    typedef DrawAttributeArrays_TTT<C4USI,N3USI,V3USI>   DrawAttributeArrays_C4iN3iV3i;
4247
4248    typedef DrawAttributeArrays_TTT_USI<C4,N3,V3>        DrawAttributeArrays_C4N3V3_i;
4249
4250
4251    typedef DrawAttributeArrays_TTT<T2,N3,V3>            DrawAttributeArrays_T2N3V3;
4252    typedef DrawAttributeArrays_TTT<T2USI,N3,V3>         DrawAttributeArrays_T2iN3V3;
4253    typedef DrawAttributeArrays_TTT<T2,N3USI,V3>         DrawAttributeArrays_T2iN3iV3;
4254    typedef DrawAttributeArrays_TTT<T2USI,N3USI,V3>      DrawAttributeArrays_T2N3iV3;
4255
4256    typedef DrawAttributeArrays_TTT<T2,N3,V3USI>         DrawAttributeArrays_T2N3V3i;
4257    typedef DrawAttributeArrays_TTT<T2USI,N3,V3USI>      DrawAttributeArrays_T2iN3V3i;
4258    typedef DrawAttributeArrays_TTT<T2,N3USI,V3USI>      DrawAttributeArrays_T2iN3iV3i;
4259    typedef DrawAttributeArrays_TTT<T2USI,N3USI,V3USI>   DrawAttributeArrays_T2N3iV3i;
4260
4261    typedef DrawAttributeArrays_TTT_USI<T2,N3,V3>        DrawAttributeArrays_T2N3V3_i;
4262
4263
4264
4265    typedef DrawAttributeArrays_TTT<T2,C4,V3>            DrawAttributeArrays_T2C4V3;
4266    typedef DrawAttributeArrays_TTT<T2USI,C4,V3>         DrawAttributeArrays_T2iC4V3;
4267    typedef DrawAttributeArrays_TTT<T2,C4USI,V3>         DrawAttributeArrays_T2C4iV3;
4268    typedef DrawAttributeArrays_TTT<T2USI,C4USI,V3>      DrawAttributeArrays_T2iC4iV3;
4269
4270    typedef DrawAttributeArrays_TTT<T2,C4,V3USI>         DrawAttributeArrays_T2C4V3i;
4271    typedef DrawAttributeArrays_TTT<T2USI,C4,V3USI>      DrawAttributeArrays_T2iC4V3i;
4272    typedef DrawAttributeArrays_TTT<T2,C4USI,V3USI>      DrawAttributeArrays_T2C4iV3i;
4273    typedef DrawAttributeArrays_TTT<T2USI,C4USI,V3USI>   DrawAttributeArrays_T2iC4iV3i;
4274
4275    typedef DrawAttributeArrays_TTT_USI<T2,C4,V3>        DrawAttributeArrays_T2C4V3_t;
4276
4277
4278    // Four attributes x 17
4279
4280    typedef DrawAttributeArrays_TTTT<T2,C4,N3,V3>                DrawAttributeArrays_T2C4N3V3;
4281    typedef DrawAttributeArrays_TTTT<T2USI,C4,N3,V3>             DrawAttributeArrays_T2iC4N3V3;
4282    typedef DrawAttributeArrays_TTTT<T2,C4USI,N3,V3>             DrawAttributeArrays_T2C4iN3V3;
4283    typedef DrawAttributeArrays_TTTT<T2USI,C4USI,N3,V3>          DrawAttributeArrays_T2iC4iN3V3;
4284
4285    typedef DrawAttributeArrays_TTTT<T2,C4,N3USI,V3>             DrawAttributeArrays_T2C4N3iV3;
4286    typedef DrawAttributeArrays_TTTT<T2USI,C4,N3USI,V3>          DrawAttributeArrays_T2iC4N3iV3;
4287    typedef DrawAttributeArrays_TTTT<T2,C4USI,N3USI,V3>           DrawAttributeArrays_T2C4iN3iV3;
4288    typedef DrawAttributeArrays_TTTT<T2USI,C4USI,N3USI,V3>       DrawAttributeArrays_T2iC4iN3iV3;
4289
4290    typedef DrawAttributeArrays_TTTT<T2,C4,N3,V3USI>             DrawAttributeArrays_T2C4N3V3i;
4291    typedef DrawAttributeArrays_TTTT<T2USI,C4,N3,V3USI>          DrawAttributeArrays_T2iC4N3V3i;
4292    typedef DrawAttributeArrays_TTTT<T2,C4USI,N3,V3USI>          DrawAttributeArrays_T2C4iN3V3i;
4293    typedef DrawAttributeArrays_TTTT<T2USI,C4USI,N3,V3USI>       DrawAttributeArrays_T2iC4iN3V3i;
4294
4295    typedef DrawAttributeArrays_TTTT<T2,C4,N3USI,V3USI>          DrawAttributeArrays_T2C4N3iV3i;
4296    typedef DrawAttributeArrays_TTTT<T2USI,C4,N3USI,V3USI>       DrawAttributeArrays_T2iC4N3iV3i;
4297    typedef DrawAttributeArrays_TTTT<T2,C4USI,N3USI,V3USI>       DrawAttributeArrays_T2C4iN3iV3i;
4298    typedef DrawAttributeArrays_TTTT<T2USI,C4USI,N3USI,V3USI>    DrawAttributeArrays_T2iC4iN3iV3i;
4299
4300    typedef DrawAttributeArrays_TTTT_USI<T2,C4,N3,V3>            DrawAttributeArrays_T2C4N3V3_i;
4301
4302    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4303
4304
4305#endif
Note: See TracBrowser for help on using the browser.