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

Revision 10621, 143.1 kB (checked in by robert, 5 years ago)

Introduced new uniforms for tracking the modelview and project matrices in shaders using non built-ins.

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