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

Revision 10615, 142.2 kB (checked in by robert, 5 years ago)

Fixed vertex attribute access bug

  • 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    afav.applyArray(VERTICES,_vertexData.array.get());
2118    afav.applyArray(NORMALS,_normalData.array.get());
2119    afav.applyArray(COLORS,_colorData.array.get());
2120    afav.applyArray(SECONDARY_COLORS,_secondaryColorData.array.get());
2121    afav.applyArray(FOG_COORDS,_fogCoordData.array.get());
2122   
2123    for(unsigned unit=0;unit<_texCoordList.size();++unit)
2124    {
2125        afav.applyArray((AttributeType)(TEXTURE_COORDS_0+unit),_texCoordList[unit].array.get());
2126    }
2127
2128    for(unsigned int index=0; index<_vertexAttribList.size(); ++index)
2129    {
2130        afav.applyArray(index,_vertexAttribList[index].array.get());
2131    }
2132}
2133
2134class ConstAttributeFunctorArrayVisitor : public ConstArrayVisitor
2135{
2136    public:
2137   
2138        ConstAttributeFunctorArrayVisitor(Drawable::ConstAttributeFunctor& af):
2139            _af(af) {}
2140   
2141        virtual ~ConstAttributeFunctorArrayVisitor() {}
2142
2143        virtual void apply(const ByteArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2144        virtual void apply(const ShortArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2145        virtual void apply(const IntArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2146        virtual void apply(const UByteArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2147        virtual void apply(const UShortArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2148        virtual void apply(const UIntArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2149        virtual void apply(const Vec4ubArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2150        virtual void apply(const FloatArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2151        virtual void apply(const Vec2Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2152        virtual void apply(const Vec3Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2153        virtual void apply(const Vec4Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2154        virtual void apply(const DoubleArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2155        virtual void apply(const Vec2dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2156        virtual void apply(const Vec3dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2157        virtual void apply(const Vec4dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2158   
2159   
2160        inline void applyArray(Drawable::AttributeType type,const Array* array)
2161        {
2162            if (array)
2163            {
2164                _type = type;
2165                array->accept(*this);
2166            }
2167        }
2168   
2169protected:
2170
2171        ConstAttributeFunctorArrayVisitor& operator = (const ConstAttributeFunctorArrayVisitor&) { return *this; }
2172
2173        Drawable::ConstAttributeFunctor&    _af;
2174        Drawable::AttributeType             _type;
2175};
2176
2177void Geometry::accept(ConstAttributeFunctor& af) const
2178{
2179    ConstAttributeFunctorArrayVisitor afav(af);
2180   
2181    afav.applyArray(VERTICES,_vertexData.array.get());
2182    afav.applyArray(NORMALS,_normalData.array.get());
2183    afav.applyArray(COLORS,_colorData.array.get());
2184    afav.applyArray(SECONDARY_COLORS,_secondaryColorData.array.get());
2185    afav.applyArray(FOG_COORDS,_fogCoordData.array.get());
2186
2187    for(unsigned unit=0;unit<_texCoordList.size();++unit)
2188    {
2189        afav.applyArray((AttributeType)(TEXTURE_COORDS_0+unit),_texCoordList[unit].array.get());
2190    }
2191
2192    for(unsigned int index=0; index<_vertexAttribList.size(); ++index)
2193    {
2194        afav.applyArray(index,_vertexAttribList[index].array.get());
2195    }
2196}
2197
2198void Geometry::accept(PrimitiveFunctor& functor) const
2199{
2200    if (!_vertexData.array.valid() || _vertexData.array->getNumElements()==0) return;
2201
2202    if (!_vertexData.indices.valid())
2203    {
2204        switch(_vertexData.array->getType())
2205        {
2206        case(Array::Vec2ArrayType):
2207            functor.setVertexArray(_vertexData.array->getNumElements(),static_cast<const Vec2*>(_vertexData.array->getDataPointer()));
2208            break;
2209        case(Array::Vec3ArrayType):
2210            functor.setVertexArray(_vertexData.array->getNumElements(),static_cast<const Vec3*>(_vertexData.array->getDataPointer()));
2211            break;
2212        case(Array::Vec4ArrayType):
2213            functor.setVertexArray(_vertexData.array->getNumElements(),static_cast<const Vec4*>(_vertexData.array->getDataPointer()));
2214            break;
2215        case(Array::Vec2dArrayType):
2216            functor.setVertexArray(_vertexData.array->getNumElements(),static_cast<const Vec2d*>(_vertexData.array->getDataPointer()));
2217            break;
2218        case(Array::Vec3dArrayType):
2219            functor.setVertexArray(_vertexData.array->getNumElements(),static_cast<const Vec3d*>(_vertexData.array->getDataPointer()));
2220            break;
2221        case(Array::Vec4dArrayType):
2222            functor.setVertexArray(_vertexData.array->getNumElements(),static_cast<const Vec4d*>(_vertexData.array->getDataPointer()));
2223            break;
2224        default:
2225            notify(WARN)<<"Warning: Geometry::accept(PrimitiveFunctor&) cannot handle Vertex Array type"<<_vertexData.array->getType()<<std::endl;
2226            return;
2227        }
2228       
2229        for(PrimitiveSetList::const_iterator itr=_primitives.begin();
2230            itr!=_primitives.end();
2231            ++itr)
2232        {
2233            (*itr)->accept(functor);
2234        }
2235    }
2236    else
2237    {
2238        const Vec2* vec2Array = 0;
2239        const Vec3* vec3Array = 0;
2240        const Vec4* vec4Array = 0;
2241        const Vec2d* vec2dArray = 0;
2242        const Vec3d* vec3dArray = 0;
2243        const Vec4d* vec4dArray = 0;
2244        Array::Type type = _vertexData.array->getType();
2245        switch(type)
2246        {
2247        case(Array::Vec2ArrayType):
2248            vec2Array = static_cast<const Vec2*>(_vertexData.array->getDataPointer());
2249            break;
2250        case(Array::Vec3ArrayType):
2251            vec3Array = static_cast<const Vec3*>(_vertexData.array->getDataPointer());
2252            break;
2253        case(Array::Vec4ArrayType):
2254            vec4Array = static_cast<const Vec4*>(_vertexData.array->getDataPointer());
2255            break;
2256        case(Array::Vec2dArrayType):
2257            vec2dArray = static_cast<const Vec2d*>(_vertexData.array->getDataPointer());
2258            break;
2259        case(Array::Vec3dArrayType):
2260            vec3dArray = static_cast<const Vec3d*>(_vertexData.array->getDataPointer());
2261            break;
2262        case(Array::Vec4dArrayType):
2263            vec4dArray = static_cast<const Vec4d*>(_vertexData.array->getDataPointer());
2264            break;
2265        default:
2266            notify(WARN)<<"Warning: Geometry::accept(PrimitiveFunctor&) cannot handle Vertex Array type"<<_vertexData.array->getType()<<std::endl;
2267            return;
2268        }
2269
2270   
2271        for(PrimitiveSetList::const_iterator itr=_primitives.begin();
2272            itr!=_primitives.end();
2273            ++itr)
2274        {
2275            const PrimitiveSet* primitiveset = itr->get();
2276            GLenum mode=primitiveset->getMode();
2277            switch(primitiveset->getType())
2278            {
2279                case(PrimitiveSet::DrawArraysPrimitiveType):
2280                {
2281                    const DrawArrays* drawArray = static_cast<const DrawArrays*>(primitiveset);
2282                    functor.begin(mode);
2283
2284                    unsigned int indexEnd = drawArray->getFirst()+drawArray->getCount();
2285                    for(unsigned int vindex=drawArray->getFirst();
2286                        vindex<indexEnd;
2287                        ++vindex)
2288                    {
2289                        switch(type)
2290                        {
2291                        case(Array::Vec2ArrayType):
2292                            functor.vertex(vec2Array[_vertexData.indices->index(vindex)]);
2293                            break;
2294                        case(Array::Vec3ArrayType):
2295                            functor.vertex(vec3Array[_vertexData.indices->index(vindex)]);
2296                            break;
2297                        case(Array::Vec4ArrayType):
2298                            functor.vertex(vec4Array[_vertexData.indices->index(vindex)]);
2299                            break;
2300                        case(Array::Vec2dArrayType):
2301                            functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]);
2302                            break;
2303                        case(Array::Vec3dArrayType):
2304                            functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]);
2305                            break;
2306                        case(Array::Vec4dArrayType):
2307                            functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]);
2308                            break;
2309                        default:
2310                            break;
2311                        }
2312
2313                    }
2314                   
2315                    functor.end();
2316                    break;
2317                }
2318                case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
2319                {
2320
2321                    const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
2322                    unsigned int vindex=drawArrayLengths->getFirst();
2323                    for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
2324                        primItr!=drawArrayLengths->end();
2325                        ++primItr)
2326                    {
2327
2328                        functor.begin(mode);
2329
2330                        for(GLsizei primCount=0;primCount<*primItr;++primCount)
2331                        {
2332                            switch(type)
2333                            {
2334                            case(Array::Vec2ArrayType):
2335                                functor.vertex(vec2Array[_vertexData.indices->index(vindex)]);
2336                                break;
2337                            case(Array::Vec3ArrayType):
2338                                functor.vertex(vec3Array[_vertexData.indices->index(vindex)]);
2339                                break;
2340                            case(Array::Vec4ArrayType):
2341                                functor.vertex(vec4Array[_vertexData.indices->index(vindex)]);
2342                                break;
2343                            case(Array::Vec2dArrayType):
2344                                functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]);
2345                                break;
2346                            case(Array::Vec3dArrayType):
2347                                functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]);
2348                                break;
2349                            case(Array::Vec4dArrayType):
2350                                functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]);
2351                                break;
2352                            default:
2353                                break;
2354                            }
2355                            ++vindex;
2356                        }
2357                       
2358                        functor.end();
2359
2360                    }
2361                    break;
2362                }
2363                case(PrimitiveSet::DrawElementsUBytePrimitiveType):
2364                {
2365                    const DrawElementsUByte* drawElements = static_cast<const DrawElementsUByte*>(primitiveset);
2366                    functor.begin(mode);
2367
2368                    unsigned int primCount=0;
2369                    for(DrawElementsUByte::const_iterator primItr=drawElements->begin();
2370                        primItr!=drawElements->end();
2371                        ++primCount,++primItr)
2372                    {
2373                        unsigned int vindex=*primItr;
2374                        switch(type)
2375                        {
2376                        case(Array::Vec2ArrayType):
2377                            functor.vertex(vec2Array[_vertexData.indices->index(vindex)]);
2378                            break;
2379                        case(Array::Vec3ArrayType):
2380                            functor.vertex(vec3Array[_vertexData.indices->index(vindex)]);
2381                            break;
2382                        case(Array::Vec4ArrayType):
2383                            functor.vertex(vec4Array[_vertexData.indices->index(vindex)]);
2384                            break;
2385                        case(Array::Vec2dArrayType):
2386                            functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]);
2387                            break;
2388                        case(Array::Vec3dArrayType):
2389                            functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]);
2390                            break;
2391                        case(Array::Vec4dArrayType):
2392                            functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]);
2393                            break;
2394                        default:
2395                            break;
2396                        }
2397                    }
2398
2399                    functor.end();
2400                    break;
2401                }
2402                case(PrimitiveSet::DrawElementsUShortPrimitiveType):
2403                {
2404                    const DrawElementsUShort* drawElements = static_cast<const DrawElementsUShort*>(primitiveset);
2405                    functor.begin(mode);
2406
2407                    for(DrawElementsUShort::const_iterator primItr=drawElements->begin();
2408                        primItr!=drawElements->end();
2409                        ++primItr)
2410                    {
2411                        unsigned int vindex=*primItr;
2412                        switch(type)
2413                        {
2414                        case(Array::Vec2ArrayType):
2415                            functor.vertex(vec2Array[_vertexData.indices->index(vindex)]);
2416                            break;
2417                        case(Array::Vec3ArrayType):
2418                            functor.vertex(vec3Array[_vertexData.indices->index(vindex)]);
2419                            break;
2420                        case(Array::Vec4ArrayType):
2421                            functor.vertex(vec4Array[_vertexData.indices->index(vindex)]);
2422                            break;
2423                        case(Array::Vec2dArrayType):
2424                            functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]);
2425                            break;
2426                        case(Array::Vec3dArrayType):
2427                            functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]);
2428                            break;
2429                        case(Array::Vec4dArrayType):
2430                            functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]);
2431                            break;
2432                        default:
2433                            break;
2434                        }
2435                    }
2436
2437                    functor.end();
2438                    break;
2439                }
2440                case(PrimitiveSet::DrawElementsUIntPrimitiveType):
2441                {
2442                    const DrawElementsUInt* drawElements = static_cast<const DrawElementsUInt*>(primitiveset);
2443                    functor.begin(mode);
2444
2445                    for(DrawElementsUInt::const_iterator primItr=drawElements->begin();
2446                        primItr!=drawElements->end();
2447                        ++primItr)
2448                    {
2449                        unsigned int vindex=*primItr;
2450                        switch(type)
2451                        {
2452                        case(Array::Vec2ArrayType):
2453                            functor.vertex(vec2Array[_vertexData.indices->index(vindex)]);
2454                            break;
2455                        case(Array::Vec3ArrayType):
2456                            functor.vertex(vec3Array[_vertexData.indices->index(vindex)]);
2457                            break;
2458                        case(Array::Vec4ArrayType):
2459                            functor.vertex(vec4Array[_vertexData.indices->index(vindex)]);
2460                            break;
2461                        case(Array::Vec2dArrayType):
2462                            functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]);
2463                            break;
2464                        case(Array::Vec3dArrayType):
2465                            functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]);
2466                            break;
2467                        case(Array::Vec4dArrayType):
2468                            functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]);
2469                            break;
2470                        default:
2471                            break;
2472                        }
2473                    }
2474
2475                    functor.end();
2476                    break;
2477                }
2478                default:
2479                {
2480                    break;
2481                }
2482            }
2483        }
2484    }
2485    return;
2486}
2487
2488void Geometry::accept(PrimitiveIndexFunctor& functor) const
2489{
2490    if (!_vertexData.array.valid() || _vertexData.array->getNumElements()==0) return;
2491
2492    switch(_vertexData.array->getType())
2493    {
2494    case(Array::Vec2ArrayType):
2495        functor.setVertexArray(_vertexData.array->getNumElements(),static_cast<const Vec2*>(_vertexData.array->getDataPointer()));
2496        break;
2497    case(Array::Vec3ArrayType):
2498        functor.setVertexArray(_vertexData.array->getNumElements(),static_cast<const Vec3*>(_vertexData.array->getDataPointer()));
2499        break;
2500    case(Array::Vec4ArrayType):
2501        functor.setVertexArray(_vertexData.array->getNumElements(),static_cast<const Vec4*>(_vertexData.array->getDataPointer()));
2502        break;
2503    case(Array::Vec2dArrayType):
2504        functor.setVertexArray(_vertexData.array->getNumElements(),static_cast<const Vec2d*>(_vertexData.array->getDataPointer()));
2505        break;
2506    case(Array::Vec3dArrayType):
2507        functor.setVertexArray(_vertexData.array->getNumElements(),static_cast<const Vec3d*>(_vertexData.array->getDataPointer()));
2508        break;
2509    case(Array::Vec4dArrayType):
2510        functor.setVertexArray(_vertexData.array->getNumElements(),static_cast<const Vec4d*>(_vertexData.array->getDataPointer()));
2511        break;
2512    default:
2513        notify(WARN)<<"Warning: Geometry::accept(PrimitiveIndexFunctor&) cannot handle Vertex Array type"<<_vertexData.array->getType()<<std::endl;
2514        return;
2515    }
2516
2517    if (!_vertexData.indices.valid())
2518    {
2519        for(PrimitiveSetList::const_iterator itr=_primitives.begin();
2520            itr!=_primitives.end();
2521            ++itr)
2522        {
2523            (*itr)->accept(functor);
2524        }
2525    }
2526    else
2527    {
2528        for(PrimitiveSetList::const_iterator itr=_primitives.begin();
2529            itr!=_primitives.end();
2530            ++itr)
2531        {
2532            const PrimitiveSet* primitiveset = itr->get();
2533            GLenum mode=primitiveset->getMode();
2534            switch(primitiveset->getType())
2535            {
2536                case(PrimitiveSet::DrawArraysPrimitiveType):
2537                {
2538                    const DrawArrays* drawArray = static_cast<const DrawArrays*>(primitiveset);
2539                    functor.begin(mode);
2540
2541                    unsigned int indexEnd = drawArray->getFirst()+drawArray->getCount();
2542                    for(unsigned int vindex=drawArray->getFirst();
2543                        vindex<indexEnd;
2544                        ++vindex)
2545                    {
2546                        functor.vertex(_vertexData.indices->index(vindex));
2547                    }
2548                   
2549                    functor.end();
2550                    break;
2551                }
2552                case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
2553                {
2554
2555                    const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
2556                    unsigned int vindex=drawArrayLengths->getFirst();
2557                    for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
2558                        primItr!=drawArrayLengths->end();
2559                        ++primItr)
2560                    {
2561
2562                        functor.begin(mode);
2563
2564                        for(GLsizei primCount=0;primCount<*primItr;++primCount)
2565                        {
2566                            functor.vertex(_vertexData.indices->index(vindex));
2567                            ++vindex;
2568                        }
2569                       
2570                        functor.end();
2571
2572                    }
2573                    break;
2574                }
2575                case(PrimitiveSet::DrawElementsUBytePrimitiveType):
2576                {
2577                    const DrawElementsUByte* drawElements = static_cast<const DrawElementsUByte*>(primitiveset);
2578                    functor.begin(mode);
2579
2580                    unsigned int primCount=0;
2581                    for(DrawElementsUByte::const_iterator primItr=drawElements->begin();
2582                        primItr!=drawElements->end();
2583                        ++primCount,++primItr)
2584                    {
2585                        unsigned int vindex=*primItr;
2586                        functor.vertex(_vertexData.indices->index(vindex));
2587                    }
2588
2589                    functor.end();
2590                    break;
2591                }
2592                case(PrimitiveSet::DrawElementsUShortPrimitiveType):
2593                {
2594                    const DrawElementsUShort* drawElements = static_cast<const DrawElementsUShort*>(primitiveset);
2595                    functor.begin(mode);
2596
2597                    for(DrawElementsUShort::const_iterator primItr=drawElements->begin();
2598                        primItr!=drawElements->end();
2599                        ++primItr)
2600                    {
2601                        unsigned int vindex=*primItr;
2602                        functor.vertex(_vertexData.indices->index(vindex));
2603                    }
2604
2605                    functor.end();
2606                    break;
2607                }
2608                case(PrimitiveSet::DrawElementsUIntPrimitiveType):
2609                {
2610                    const DrawElementsUInt* drawElements = static_cast<const DrawElementsUInt*>(primitiveset);
2611                    functor.begin(mode);
2612
2613                    for(DrawElementsUInt::const_iterator primItr=drawElements->begin();
2614                        primItr!=drawElements->end();
2615                        ++primItr)
2616                    {
2617                        unsigned int vindex=*primItr;
2618                        functor.vertex(_vertexData.indices->index(vindex));
2619                    }
2620
2621                    functor.end();
2622                    break;
2623                }
2624                default:
2625                {
2626                    break;
2627                }
2628            }
2629        }
2630    }
2631    return;
2632}
2633
2634unsigned int _computeNumberOfPrimitives(const osg::Geometry& geom)
2635{
2636
2637    unsigned int totalNumberOfPrimitives = 0;
2638   
2639    for(Geometry::PrimitiveSetList::const_iterator itr=geom.getPrimitiveSetList().begin();
2640        itr!=geom.getPrimitiveSetList().end();
2641        ++itr)
2642    {
2643        const PrimitiveSet* primitiveset = itr->get();
2644        GLenum mode=primitiveset->getMode();
2645
2646        unsigned int primLength;
2647        switch(mode)
2648        {
2649            case(GL_POINTS):    primLength=1; osg::notify(osg::INFO)<<"prim=GL_POINTS"<<std::endl; break;
2650            case(GL_LINES):     primLength=2; osg::notify(osg::INFO)<<"prim=GL_LINES"<<std::endl; break;
2651            case(GL_TRIANGLES): primLength=3; osg::notify(osg::INFO)<<"prim=GL_TRIANGLES"<<std::endl; break;
2652            case(GL_QUADS):     primLength=4; osg::notify(osg::INFO)<<"prim=GL_QUADS"<<std::endl; break;
2653            default:            primLength=0; osg::notify(osg::INFO)<<"prim="<<std::hex<<mode<<std::dec<<std::endl; break; // compute later when =0.
2654        }
2655
2656        // draw primitives by the more flexible "slow" path,
2657        // sending OpenGL glBegin/glVertex.../glEnd().
2658        switch(primitiveset->getType())
2659        {
2660            case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
2661            {
2662
2663                const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
2664                for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
2665                    primItr!=drawArrayLengths->end();
2666                    ++primItr)
2667                {
2668                    if (primLength==0) totalNumberOfPrimitives += 1;
2669                    else totalNumberOfPrimitives += *primItr/primLength;
2670                }
2671                break;
2672            }
2673            default:
2674            {
2675                if (primLength==0) { totalNumberOfPrimitives += 1; osg::notify(osg::INFO)<<"   totalNumberOfPrimitives="<<totalNumberOfPrimitives<<std::endl;}
2676                else { totalNumberOfPrimitives += primitiveset->getNumIndices()/primLength; osg::notify(osg::INFO)<<"   primitiveset->getNumIndices()="<<primitiveset->getNumIndices()<<" totalNumberOfPrimitives="<<totalNumberOfPrimitives<<std::endl; }
2677
2678            }
2679        }
2680    }
2681
2682    return totalNumberOfPrimitives;
2683}
2684
2685template<class A>
2686bool _verifyBindings(const osg::Geometry& geom, const A& arrayData)
2687{
2688    unsigned int numElements = arrayData.indices.valid()?arrayData.indices->getNumElements():
2689                               arrayData.array.valid()?arrayData.array->getNumElements():0;
2690
2691    switch(arrayData.binding)
2692    {
2693        case(osg::Geometry::BIND_OFF):
2694            if (numElements>0) return false;
2695            break;
2696        case(osg::Geometry::BIND_OVERALL):
2697            if (numElements!=1) return false;
2698            break;
2699        case(osg::Geometry::BIND_PER_PRIMITIVE_SET):
2700            if (numElements!=geom.getPrimitiveSetList().size()) return false;
2701            break;
2702        case(osg::Geometry::BIND_PER_PRIMITIVE):
2703            if (numElements!=_computeNumberOfPrimitives(geom)) return false;
2704            break;
2705        case(osg::Geometry::BIND_PER_VERTEX):
2706        {
2707            unsigned int numVertices = geom.getVertexIndices()?geom.getVertexIndices()->getNumElements():
2708                                       geom.getVertexArray()?geom.getVertexArray()->getNumElements():0;
2709            if (numElements!=numVertices) return false;       
2710            break;
2711        }
2712    }
2713    return true;
2714}
2715
2716template<class A>
2717void _computeCorrectBindingsAndArraySizes(std::ostream& out, const osg::Geometry& geom, A& arrayData, const char* arrayName)
2718{
2719    unsigned int numElements = arrayData.indices.valid()?arrayData.indices->getNumElements():
2720                               arrayData.array.valid()?arrayData.array->getNumElements():0;
2721
2722    // check to see if binding matches 0 elements required.
2723    if (numElements==0)
2724    {
2725        // correct binding if not correct.
2726        if (arrayData.binding!=osg::Geometry::BIND_OFF)
2727        {
2728            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() "<<std::endl
2729                   <<"         "<<arrayName<<" binding has been reset to BIND_OFF"<<std::endl;
2730            arrayData.binding=osg::Geometry::BIND_OFF;
2731        }
2732        return;
2733    }
2734
2735    // check to see if binding matches 1 elements required.
2736    if (numElements==1)
2737    {
2738        // correct binding if not correct.
2739        if (arrayData.binding!=osg::Geometry::BIND_OVERALL)
2740        {
2741            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() "<<std::endl
2742                   <<"         "<<arrayName<<" binding has been reset to BIND_OVERALL"<<std::endl;
2743            arrayData.binding=osg::Geometry::BIND_OVERALL;
2744        }
2745        return;
2746    }
2747
2748
2749    unsigned int numVertices = geom.getVertexIndices()?geom.getVertexIndices()->getNumElements():
2750                               geom.getVertexArray()?geom.getVertexArray()->getNumElements():0;
2751   
2752    if ( numVertices==0 )
2753    {
2754        if (arrayData.binding!=osg::Geometry::BIND_OFF)
2755        {
2756            arrayData.array = 0;
2757            arrayData.indices = 0;
2758            arrayData.binding = osg::Geometry::BIND_OFF;
2759            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() vertex array is empty but "<<std::endl
2760                <<"         vertex array is empty but"<<arrayName<<" is set"<<std::endl
2761                <<"         reseting "<<arrayName<< " binding to BIND_OFF and array & indices to 0."<<std::endl;
2762        }
2763    }
2764   
2765    if (numElements==numVertices)
2766    {
2767        // correct the binding to per vertex.
2768        if (arrayData.binding!=osg::Geometry::BIND_PER_VERTEX)
2769        {
2770            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() "<<std::endl
2771                   <<"         "<<arrayName<<" binding has been reset to BIND_PER_VERTEX"<<std::endl;
2772            arrayData.binding = osg::Geometry::BIND_PER_VERTEX;
2773        }
2774        return;
2775    }
2776
2777
2778
2779    // check to see if binding might be per primitive set   
2780    unsigned int numPrimitiveSets = geom.getPrimitiveSetList().size();
2781   
2782    if (numElements==numPrimitiveSets)
2783    {
2784        if (arrayData.binding != osg::Geometry::BIND_PER_PRIMITIVE_SET)
2785        {
2786            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() "<<std::endl
2787                   <<"         "<<arrayName<<" binding has been reset to BIND_PER_PRIMITIVE_SET"<<std::endl;
2788            arrayData.binding = osg::Geometry::BIND_PER_PRIMITIVE_SET;
2789        }
2790        return;
2791    }
2792   
2793    // check to see if binding might be per primitive   
2794    unsigned int numPrimitives = _computeNumberOfPrimitives(geom);
2795    if (numElements==numPrimitives)
2796    {
2797        if (arrayData.binding != osg::Geometry::BIND_PER_PRIMITIVE)
2798        {
2799            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() "<<std::endl
2800                   <<"         "<<arrayName<<" binding has been reset to BIND_PER_PRIMITIVE"<<std::endl;
2801            arrayData.binding = osg::Geometry::BIND_PER_PRIMITIVE;
2802        }
2803        return;
2804    }
2805
2806    if (numElements>numVertices)
2807    {
2808        arrayData.binding = osg::Geometry::BIND_PER_VERTEX;
2809        return;
2810    }
2811    if (numElements>numPrimitives)
2812    {
2813        arrayData.binding = osg::Geometry::BIND_PER_PRIMITIVE;
2814        return;
2815    }
2816    if (numElements>numPrimitiveSets)
2817    {
2818        arrayData.binding = osg::Geometry::BIND_PER_PRIMITIVE_SET;
2819        return;
2820    }
2821    if (numElements>=1)
2822    {
2823        arrayData.binding = osg::Geometry::BIND_OVERALL;
2824        return;
2825    }
2826    arrayData.binding = osg::Geometry::BIND_OFF;
2827 
2828}       
2829
2830bool Geometry::verifyBindings(const ArrayData& arrayData) const
2831{
2832    return _verifyBindings(*this,arrayData);
2833}
2834
2835bool Geometry::verifyBindings(const Vec3ArrayData& arrayData) const
2836{
2837    return _verifyBindings(*this,arrayData);
2838}
2839
2840void Geometry::computeCorrectBindingsAndArraySizes(ArrayData& arrayData, const char* arrayName)
2841{
2842    _computeCorrectBindingsAndArraySizes(osg::notify(osg::INFO),*this,arrayData,arrayName);
2843}
2844
2845void Geometry::computeCorrectBindingsAndArraySizes(Vec3ArrayData& arrayData, const char* arrayName)
2846{
2847    _computeCorrectBindingsAndArraySizes(osg::notify(osg::INFO),*this,arrayData,arrayName);
2848}
2849
2850bool Geometry::verifyBindings() const
2851{
2852    if (!verifyBindings(_normalData)) return false;
2853    if (!verifyBindings(_colorData)) return false;
2854    if (!verifyBindings(_secondaryColorData)) return false;
2855    if (!verifyBindings(_fogCoordData)) return false;
2856
2857    for(ArrayDataList::const_iterator titr=_texCoordList.begin();
2858        titr!=_texCoordList.end();
2859        ++titr)
2860    {
2861        if (!verifyBindings(*titr)) return false;
2862    }
2863
2864    for(ArrayDataList::const_iterator vitr=_vertexAttribList.begin();
2865        vitr!=_vertexAttribList.end();
2866        ++vitr)
2867    {
2868        if (!verifyBindings(*vitr)) return false;
2869    }
2870
2871    return true;
2872}
2873
2874void Geometry::computeCorrectBindingsAndArraySizes()
2875{
2876    // if (verifyBindings()) return;
2877   
2878    computeCorrectBindingsAndArraySizes(_normalData,"_normalData");
2879    computeCorrectBindingsAndArraySizes(_colorData,"_colorData");
2880    computeCorrectBindingsAndArraySizes(_secondaryColorData,"_secondaryColorData");
2881    computeCorrectBindingsAndArraySizes(_fogCoordData,"_fogCoordData");
2882
2883    for(ArrayDataList::iterator titr=_texCoordList.begin();
2884        titr!=_texCoordList.end();
2885        ++titr)
2886    {
2887        computeCorrectBindingsAndArraySizes(*titr,"_texCoordList[]");
2888    }
2889
2890    for(ArrayDataList::iterator vitr=_vertexAttribList.begin();
2891        vitr!=_vertexAttribList.end();
2892        ++vitr)
2893    {
2894        computeCorrectBindingsAndArraySizes(*vitr,"_vertAttribList[]");
2895    }
2896}
2897
2898class ExpandIndexedArray : public osg::ConstArrayVisitor
2899{
2900    public:
2901        ExpandIndexedArray(const osg::IndexArray& indices,Array* targetArray):
2902            _indices(indices),
2903            _targetArray(targetArray) {}
2904       
2905        virtual ~ExpandIndexedArray() {}
2906
2907        // Create when both of the arrays are predefined templated classes. We
2908        // can do some optimizations in this case that aren't possible in the general
2909        // case.
2910        template <class T,class I>
2911        T* create_inline(const T& array,const I& indices)
2912        {
2913            T* newArray = 0;
2914
2915            // if source array type and target array type are equal but arrays arn't equal
2916            if (_targetArray && _targetArray->getType()==array.getType() && _targetArray!=(osg::Array*)(&array))
2917            {
2918                // reuse exisiting target array
2919                newArray = static_cast<T*>(_targetArray);
2920                if (newArray->size()!=indices.size())
2921                {
2922                    // make sure its the right size
2923                    newArray->resize(indices.size());
2924                }
2925            }
2926            else
2927            {
2928                //  else create a new array.
2929                newArray = new T(indices.size());
2930            }
2931
2932            for(unsigned int i=0;i<indices.size();++i)
2933            {
2934                (*newArray)[i]= array[indices[i]];
2935            }
2936
2937            return newArray;
2938        }
2939
2940        // Create when one of the arrays isn't one of the predefined templated classes. The
2941        // template parameter is the type of the array that will get created. This is  always
2942        // one of the predefined classes. We could call clone to get one of the same type as
2943        // the input array, but the interface of the osg::Array class doesn't include a way
2944        // to set an element.
2945        template <class T>
2946        osg::Array* create_noinline(const osg::Array& array, const osg::IndexArray& indices)
2947        {
2948            T* newArray = 0;
2949            typedef typename T::ElementDataType EDT;
2950
2951            unsigned int num_indices = indices.getNumElements();
2952            newArray = new T(num_indices);
2953
2954            const EDT* src = static_cast<const EDT*>(array.getDataPointer());
2955
2956            for(unsigned int i=0;i<num_indices;++i)
2957            {
2958                (*newArray)[i]= src[indices.index(i)];
2959            }
2960
2961            return newArray;
2962        }
2963
2964        osg::Array* create_noinline(const osg::Array& array, const osg::IndexArray& indices)
2965        {
2966            switch (array.getType())
2967            {
2968                case(osg::Array::ByteArrayType):   return create_noinline<osg::ByteArray>(array,indices);
2969                case(osg::Array::ShortArrayType):  return create_noinline<osg::ShortArray>(array,indices);
2970                case(osg::Array::IntArrayType):    return create_noinline<osg::IntArray>(array,indices);
2971                case(osg::Array::UByteArrayType):  return create_noinline<osg::UByteArray>(array,indices);
2972                case(osg::Array::UShortArrayType): return create_noinline<osg::UShortArray>(array,indices);
2973                case(osg::Array::UIntArrayType):   return create_noinline<osg::UIntArray>(array,indices);
2974                case(osg::Array::Vec4ubArrayType): return create_noinline<osg::Vec4ubArray>(array,indices);
2975                case(osg::Array::FloatArrayType):  return create_noinline<osg::FloatArray>(array,indices);
2976                case(osg::Array::Vec2ArrayType):   return create_noinline<osg::Vec2Array>(array,indices);
2977                case(osg::Array::Vec3ArrayType):   return create_noinline<osg::Vec3Array>(array,indices);
2978                case(osg::Array::Vec4ArrayType):   return create_noinline<osg::Vec4Array>(array,indices);
2979                case(osg::Array::Vec2dArrayType):   return create_noinline<osg::Vec2dArray>(array,indices);
2980                case(osg::Array::Vec3dArrayType):   return create_noinline<osg::Vec3dArray>(array,indices);
2981                case(osg::Array::Vec4dArrayType):   return create_noinline<osg::Vec4dArray>(array,indices);
2982                default:
2983                    return NULL;
2984            }
2985        }
2986
2987        template <class TA, class TI>
2988        osg::Array* create(const TA& array, const osg::IndexArray& indices)
2989        {
2990            // We know that indices.getType returned the same thing as TI, but
2991            // we need to determine whether it is really an instance of TI, or
2992            // perhaps another subclass of osg::Array that contains the same
2993            // type of data.
2994            const TI* ba(dynamic_cast<const TI*>(&indices));
2995            if (ba != NULL) {
2996                return create_inline(array,*ba);
2997            }
2998            else {
2999                return create_noinline(array, _indices);
3000            }
3001        }
3002
3003        template <class T>
3004        osg::Array* create(const T& array)
3005        {
3006            switch(_indices.getType())
3007            {
3008            case(osg::Array::ByteArrayType):   return create<T, osg::ByteArray>(array, _indices);
3009            case(osg::Array::ShortArrayType):  return create<T, osg::ShortArray>(array, _indices);
3010            case(osg::Array::IntArrayType):    return create<T, osg::IntArray>(array, _indices);
3011            case(osg::Array::UByteArrayType):  return create<T, osg::UByteArray>(array, _indices);
3012            case(osg::Array::UShortArrayType): return create<T, osg::UShortArray>(array, _indices);
3013            case(osg::Array::UIntArrayType):   return create<T, osg::UIntArray>(array, _indices);
3014            default:                           return create_noinline(array, _indices);
3015            }
3016           
3017        }
3018
3019        // applys for the predefined classes go through 1-arg create to do indexing
3020        virtual void apply(const osg::ByteArray& array) { _targetArray = create(array); }
3021        virtual void apply(const osg::ShortArray& array) { _targetArray = create(array); }
3022        virtual void apply(const osg::IntArray& array) { _targetArray = create(array); }
3023        virtual void apply(const osg::UByteArray& array) { _targetArray = create(array); }
3024        virtual void apply(const osg::UShortArray& array) { _targetArray = create(array); }
3025        virtual void apply(const osg::UIntArray& array) { _targetArray = create(array); }
3026        virtual void apply(const osg::Vec4ubArray& array) { _targetArray = create(array); }
3027        virtual void apply(const osg::FloatArray& array) { _targetArray = create(array); }
3028        virtual void apply(const osg::Vec2Array& array) { _targetArray = create(array); }
3029        virtual void apply(const osg::Vec3Array& array) { _targetArray = create(array); }
3030        virtual void apply(const osg::Vec4Array& array) { _targetArray = create(array); }
3031
3032        // other subclasses of osg::Array end up here
3033        virtual void apply(const osg::Array& array) { _targetArray = create_noinline(array, _indices); }
3034
3035        const osg::IndexArray& _indices;
3036        osg::Array* _targetArray;
3037
3038    protected:
3039
3040        ExpandIndexedArray& operator = (const ExpandIndexedArray&) { return *this; }
3041
3042};
3043
3044bool Geometry::suitableForOptimization() const
3045{
3046    bool hasIndices = false;
3047
3048    if (getVertexIndices()) hasIndices = true;
3049
3050    if (getNormalIndices()) hasIndices = true;
3051
3052    if (getColorIndices()) hasIndices = true;
3053
3054    if (getSecondaryColorIndices()) hasIndices = true;
3055
3056    if (getFogCoordIndices()) hasIndices = true;
3057
3058    for(unsigned int ti=0;ti<getNumTexCoordArrays();++ti)
3059    {
3060        if (getTexCoordIndices(ti)) hasIndices = true;
3061    }
3062   
3063    for(unsigned int vi=0;vi<getNumVertexAttribArrays();++vi)
3064    {
3065        if (getVertexAttribIndices(vi)) hasIndices = true;
3066    }
3067
3068    return hasIndices;
3069}
3070
3071void Geometry::copyToAndOptimize(Geometry& target)
3072{
3073    bool copyToSelf = (this==&target);
3074
3075    // copy over primitive sets.
3076    if (!copyToSelf) target.getPrimitiveSetList() = getPrimitiveSetList();
3077
3078    // copy over attribute arrays.
3079    if (getVertexIndices() && getVertexArray())
3080    {
3081        ExpandIndexedArray eia(*(getVertexIndices()),target.getVertexArray());
3082        getVertexArray()->accept(eia);
3083
3084        target.setVertexArray(eia._targetArray);
3085        target.setVertexIndices(0);
3086    }
3087    else if (getVertexArray())
3088    {
3089        if (!copyToSelf) target.setVertexArray(getVertexArray());
3090    }
3091
3092    target.setNormalBinding(getNormalBinding());
3093    if (getNormalIndices() && getNormalArray())
3094    {
3095        ExpandIndexedArray eia(*(getNormalIndices()),target.getNormalArray());
3096        getNormalArray()->accept(eia);
3097
3098        target.setNormalArray(dynamic_cast<osg::Vec3Array*>(eia._targetArray));
3099        target.setNormalIndices(0);
3100    }
3101    else if (getNormalArray())
3102    {
3103        if (!copyToSelf) target.setNormalArray(getNormalArray());
3104    }
3105
3106    target.setColorBinding(getColorBinding());
3107    if (getColorIndices() && getColorArray())
3108    {
3109        ExpandIndexedArray eia(*(getColorIndices()),target.getColorArray());
3110        getColorArray()->accept(eia);
3111
3112        target.setColorArray(eia._targetArray);
3113        target.setColorIndices(0);
3114    }
3115    else if (getColorArray())
3116    {
3117        if (!copyToSelf) target.setColorArray(getColorArray());
3118    }
3119
3120    target.setSecondaryColorBinding(getSecondaryColorBinding());
3121    if (getSecondaryColorIndices() && getSecondaryColorArray())
3122    {
3123        ExpandIndexedArray eia(*(getSecondaryColorIndices()),target.getSecondaryColorArray());
3124        getSecondaryColorArray()->accept(eia);
3125
3126        target.setSecondaryColorArray(eia._targetArray);
3127        target.setSecondaryColorIndices(0);
3128    }
3129    else if (getSecondaryColorArray())
3130    {
3131        if (!copyToSelf) target.setSecondaryColorArray(getSecondaryColorArray());
3132    }
3133
3134    target.setFogCoordBinding(getFogCoordBinding());
3135    if (getFogCoordIndices() && getFogCoordArray())
3136    {
3137        ExpandIndexedArray eia(*(getFogCoordIndices()),target.getFogCoordArray());
3138        getFogCoordArray()->accept(eia);
3139
3140        target.setFogCoordArray(eia._targetArray);
3141        target.setFogCoordIndices(0);
3142    }
3143    else if (getFogCoordArray())
3144    {
3145        if (!copyToSelf) target.setFogCoordArray(getFogCoordArray());
3146    }
3147
3148    for(unsigned int ti=0;ti<getNumTexCoordArrays();++ti)
3149    {
3150        if (getTexCoordIndices(ti) && getTexCoordArray(ti))
3151        {
3152            ExpandIndexedArray eia(*(getTexCoordIndices(ti)),target.getTexCoordArray(ti));
3153           
3154            getTexCoordArray(ti)->accept(eia);
3155
3156            target.setTexCoordArray(ti,eia._targetArray);
3157            target.setTexCoordIndices(ti,0);
3158        }
3159        else if (getTexCoordArray(ti))
3160        {
3161            if (!copyToSelf) target.setTexCoordArray(ti,getTexCoordArray(ti));
3162        }
3163    }
3164   
3165    for(unsigned int vi=0;vi<_vertexAttribList.size();++vi)
3166    {
3167        ArrayData& arrayData = _vertexAttribList[vi];
3168        if (arrayData.indices.valid())
3169        {
3170            ExpandIndexedArray eia(*arrayData.indices,target.getVertexAttribArray(vi));
3171            arrayData.array->accept(eia);
3172            target.setVertexAttribData(vi,ArrayData(eia._targetArray, 0, arrayData.binding, arrayData.normalize));
3173        }
3174        else if (arrayData.array.valid())
3175        {
3176            if (!copyToSelf) target.setVertexAttribData(vi,arrayData);
3177        }
3178    }
3179}
3180
3181bool Geometry::containsSharedArrays() const
3182{
3183    unsigned int numSharedArrays = 0;
3184   
3185    if (getVertexArray() && getVertexArray()->referenceCount()>1) ++numSharedArrays;
3186    if (getNormalArray() && getNormalArray()->referenceCount()>1) ++numSharedArrays;
3187    if (getColorArray() && getColorArray()->referenceCount()>1) ++numSharedArrays;
3188    if (getSecondaryColorArray() && getSecondaryColorArray()->referenceCount()>1) ++numSharedArrays;
3189    if (getFogCoordArray() && getFogCoordArray()->referenceCount()>1) ++numSharedArrays;
3190
3191    for(unsigned int ti=0;ti<getNumTexCoordArrays();++ti)
3192    {
3193        if (getTexCoordArray(ti) && getTexCoordArray(ti)->referenceCount()>1) ++numSharedArrays;
3194    }
3195   
3196    for(unsigned int vi=0;vi<_vertexAttribList.size();++vi)
3197    {
3198        const ArrayData& arrayData = _vertexAttribList[vi];
3199        if (arrayData.array.valid() && arrayData.array->referenceCount()>1) ++numSharedArrays;
3200    }
3201    return numSharedArrays!=0;
3202}
3203
3204void Geometry::duplicateSharedArrays()
3205{
3206    #define DUPLICATE_IF_REQUIRED(A) \
3207        if (get##A() && get##A()->referenceCount()>1) \
3208        { \
3209            set##A(dynamic_cast<osg::Array*>(get##A()->clone(osg::CopyOp::DEEP_COPY_ARRAYS))); \
3210        }
3211
3212    DUPLICATE_IF_REQUIRED(VertexArray)
3213    DUPLICATE_IF_REQUIRED(NormalArray)
3214    DUPLICATE_IF_REQUIRED(ColorArray)
3215    DUPLICATE_IF_REQUIRED(SecondaryColorArray)
3216    DUPLICATE_IF_REQUIRED(FogCoordArray)
3217
3218    for(unsigned int ti=0;ti<getNumTexCoordArrays();++ti)
3219    {
3220        if (getTexCoordArray(ti) && getTexCoordArray(ti)->referenceCount()>1)
3221        {
3222            setTexCoordArray(ti, dynamic_cast<osg::Array*>(getTexCoordArray(ti)->clone(osg::CopyOp::DEEP_COPY_ARRAYS)));
3223        }
3224    }
3225   
3226    for(unsigned int vi=0;vi<_vertexAttribList.size();++vi)
3227    {
3228        ArrayData& arrayData = _vertexAttribList[vi];
3229        if (arrayData.array.valid() && arrayData.array->referenceCount()>1)
3230        {
3231            arrayData.array = dynamic_cast<osg::Array*>(arrayData.array->clone(osg::CopyOp::DEEP_COPY_ARRAYS));
3232        }
3233    }
3234}
3235
3236void Geometry::computeInternalOptimizedGeometry()
3237{
3238    if (suitableForOptimization())
3239    {
3240        if (!_internalOptimizedGeometry) _internalOptimizedGeometry = new Geometry;
3241
3242        copyToAndOptimize(*_internalOptimizedGeometry);
3243    }
3244}
3245
3246
3247Geometry* osg::createTexturedQuadGeometry(const Vec3& corner,const Vec3& widthVec,const Vec3& heightVec, float l, float b, float r, float t)
3248{
3249    Geometry* geom = new Geometry;
3250
3251    Vec3Array* coords = new Vec3Array(4);
3252    (*coords)[0] = corner+heightVec;
3253    (*coords)[1] = corner;
3254    (*coords)[2] = corner+widthVec;
3255    (*coords)[3] = corner+widthVec+heightVec;
3256    geom->setVertexArray(coords);
3257
3258    Vec2Array* tcoords = new Vec2Array(4);
3259    (*tcoords)[0].set(l,t);
3260    (*tcoords)[1].set(l,b);
3261    (*tcoords)[2].set(r,b);
3262    (*tcoords)[3].set(r,t);
3263    geom->setTexCoordArray(0,tcoords);
3264
3265    osg::Vec4Array* colours = new osg::Vec4Array(1);
3266    (*colours)[0].set(1.0f,1.0f,1.0,1.0f);
3267    geom->setColorArray(colours);
3268    geom->setColorBinding(Geometry::BIND_OVERALL);
3269
3270    osg::Vec3Array* normals = new osg::Vec3Array(1);
3271    (*normals)[0] = widthVec^heightVec;
3272    (*normals)[0].normalize();
3273    geom->setNormalArray(normals);
3274    geom->setNormalBinding(Geometry::BIND_OVERALL);
3275
3276    geom->addPrimitiveSet(new DrawArrays(PrimitiveSet::QUADS,0,4));
3277   
3278    return geom;
3279}
3280
3281
3282
3283
3284///////////////////////////////////////////////////////////////////////////////////////////////
3285///////////////////////////////////////////////////////////////////////////////////////////////
3286///////////////////////////////////////////////////////////////////////////////////////////////
3287///////////////////////////////////////////////////////////////////////////////////////////////
3288///////////////////////////////////////////////////////////////////////////////////////////////
3289///////////////////////////////////////////////////////////////////////////////////////////////
3290///////////////////////////////////////////////////////////////////////////////////////////////
3291
3292
3293// experimental templated rendering code, please ignore...
3294// will move to osg::Geometry once complete.
3295// Robert Osfield, August 2003.
3296#if 0
3297
3298    struct DrawAttributeArrays
3299    {
3300        virtual bool valid() const = 0;
3301        virtual void set(osg::Geometry* geometry) = 0;
3302        virtual unsigned int draw(unsigned int index, unsigned int count) const = 0;
3303    };
3304
3305    struct V3
3306    {
3307        V3():_array(0) {}
3308
3309        bool valid() const { return _array!=0; }
3310
3311        void set(osg::Geometry* geometry)
3312        {
3313            _array = 0;
3314            osg::Array* array = geometry->getVertexArray();
3315            if (array && array->getType()==osg::Array::Vec3ArrayType)
3316            {
3317                osg::Vec3Array* vec3array = static_cast<osg::Vec3Array*>(array);
3318                if (!vec3array->empty()) _array = &(vec3array->front());
3319            }
3320        }
3321
3322        inline void draw(unsigned int index) const
3323        {
3324            glVertex3fv(_array[index].ptr());
3325        }
3326
3327        osg::Vec3* _array;
3328    };
3329
3330    struct V3USI
3331    {
3332        V3USI():_array(0),_indices(0) {}
3333
3334        bool valid() const { return _array!=0 && _indices!=0; }
3335
3336        void set(osg::Geometry* geometry)
3337        {
3338            _array = 0;
3339            osg::Array* array = geometry->getVertexArray();
3340            if (array && array->getType()==osg::Array::Vec3ArrayType)
3341            {
3342                osg::Vec3Array* vec3array = static_cast<osg::Vec3Array*>(array);
3343                if (!vec3array->empty()) _array = &(vec3array->front());
3344            }
3345
3346            _indices = 0;
3347            osg::IndexArray* indices = geometry->getVertexIndices();
3348            if (indices && indices->getType()==osg::Array::UShortArrayType)
3349            {
3350                osg::UShortArray* ushort3array = static_cast<osg::UShortArray*>(array);
3351                if (!ushort3array->empty()) _indices = &(ushort3array->front());
3352            }
3353        }
3354
3355        inline void draw(unsigned int index) const
3356        {
3357            glVertex3fv(_array[_indices[index]].ptr());
3358        }
3359
3360        osg::Vec3*      _array;
3361        unsigned short* _indices;
3362    };
3363
3364    //////////////////////////////
3365
3366    struct N3
3367    {
3368        N3():_array(0) {}
3369
3370        bool valid() const { return _array!=0; }
3371
3372        void set(osg::Geometry* geometry)
3373        {
3374            _array = 0;
3375            osg::Array* array = geometry->getVertexArray();
3376            if (array && array->getType()==osg::Array::Vec3ArrayType)
3377            {
3378                osg::Vec3Array* vec3array = static_cast<osg::Vec3Array*>(array);
3379                if (!vec3array->empty()) _array = &(vec3array->front());
3380            }
3381        }
3382
3383        inline void draw(unsigned int index) const
3384        {
3385            glNormal3fv(_array[index].ptr());
3386        }
3387
3388        osg::Vec3* _array;
3389    };
3390
3391    struct N3USI
3392    {
3393        N3USI():_array(0),_indices(0) {}
3394
3395        bool valid() const { return _array!=0 && _indices!=0; }
3396
3397        void set(osg::Geometry* geometry)
3398        {
3399            _array = 0;
3400            osg::Array* array = geometry->getVertexArray();
3401            if (array && array->getType()==osg::Array::Vec3ArrayType)
3402            {
3403                osg::Vec3Array* vec3array = static_cast<osg::Vec3Array*>(array);
3404                if (!vec3array->empty()) _array = &(vec3array->front());
3405            }
3406
3407            _indices = 0;
3408            osg::IndexArray* indices = geometry->getVertexIndices();
3409            if (indices && indices->getType()==osg::Array::UShortArrayType)
3410            {
3411                osg::UShortArray* ushortarray = static_cast<osg::UShortArray*>(array);
3412                if (!ushortarray->empty()) _indices = &(ushortarray->front());
3413            }
3414        }
3415
3416        inline void draw(unsigned int index) const
3417        {
3418            glNormal3fv(_array[_indices[index]].ptr());
3419        }
3420
3421        osg::Vec3*      _array;
3422        unsigned short* _indices;
3423    };
3424
3425    //////////////////////////////
3426
3427    struct C4
3428    {
3429        C4():_array(0) {}
3430
3431        bool valid() const { return _array!=0; }
3432
3433        void set(osg::Geometry* geometry)
3434        {
3435            _array = 0;
3436            osg::Array* array = geometry->getColorArray();
3437            if (array && array->getType()==osg::Array::Vec4ArrayType)
3438            {
3439                osg::Vec4Array* vec4array = static_cast<osg::Vec4Array*>(array);
3440                if (!vec4array->empty()) _array = &(vec4array->front());
3441            }
3442        }
3443
3444        inline void draw(unsigned int index) const
3445        {
3446            glVertex3fv(_array[index].ptr());
3447        }
3448
3449        osg::Vec4* _array;
3450    };
3451
3452    struct C4USI
3453    {
3454        C4USI():_array(0),_indices(0) {}
3455
3456        bool valid() const { return _array!=0 && _indices!=0; }
3457
3458        void set(osg::Geometry* geometry)
3459        {
3460            _array = 0;
3461            osg::Array* array = geometry->getColorArray();
3462            if (array && array->getType()==osg::Array::Vec4ArrayType)
3463            {
3464                osg::Vec4Array* vec4array = static_cast<osg::Vec4Array*>(array);
3465                if (!vec4array->empty()) _array = &(vec4array->front());
3466            }
3467
3468            _indices = 0;
3469            osg::IndexArray* indices = geometry->getColorIndices();
3470            if (indices && indices->getType()==osg::Array::UShortArrayType)
3471            {
3472                osg::UShortArray* ushortarray = static_cast<osg::UShortArray*>(array);
3473                if (!ushortarray->empty()) _indices = &(ushortarray->front());
3474            }
3475        }
3476
3477        inline void draw(unsigned int index) const
3478        {
3479            glColor4fv(_array[_indices[index]].ptr());
3480        }
3481
3482        osg::Vec4*      _array;
3483        unsigned short* _indices;
3484    };
3485
3486    //////////////////////////////
3487
3488    struct T2
3489    {
3490        T2():_array(0) {}
3491
3492        bool valid() const { return _array!=0; }
3493
3494        void set(osg::Geometry* geometry)
3495        {
3496            _array = 0;
3497            osg::Array* array = geometry->getTexCoordArray(0);
3498            if (array && array->getType()==osg::Array::Vec2ArrayType)
3499            {
3500                osg::Vec2Array* vec2array = static_cast<osg::Vec2Array*>(array);
3501                if (!vec2array->empty()) _array = &(vec2array->front());
3502            }
3503        }
3504
3505        inline void draw(unsigned int index) const
3506        {
3507            glTexCoord2fv(_array[index].ptr());
3508        }
3509
3510        osg::Vec2* _array;
3511    };
3512
3513    struct T2USI
3514    {
3515        T2USI():_array(0),_indices(0) {}
3516
3517        bool valid() const { return _array!=0 && _indices!=0; }
3518
3519        void set(osg::Geometry* geometry)
3520        {
3521            _array = 0;
3522            osg::Array* array = geometry->getTexCoordArray(0);
3523            if (array && array->getType()==osg::Array::Vec2ArrayType)
3524            {
3525                osg::Vec2Array* vec2array = static_cast<osg::Vec2Array*>(array);
3526                if (!vec2array->empty()) _array = &(vec2array->front());
3527            }
3528
3529            _indices = 0;
3530            osg::IndexArray* indices = geometry->getTexCoordIndices(0);
3531            if (indices && indices->getType()==osg::Array::UShortArrayType)
3532            {
3533                osg::UShortArray* ushortarray = static_cast<osg::UShortArray*>(array);
3534                if (!ushortarray->empty()) _indices = &(ushortarray->front());
3535            }
3536        }
3537
3538        inline void draw(unsigned int index) const
3539        {
3540            glTexCoord2fv(_array[_indices[index]].ptr());
3541        }
3542
3543        osg::Vec2*      _array;
3544        unsigned short* _indices;
3545    };
3546
3547
3548    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3549
3550    template < class T1 >
3551    struct DrawAttributeArrays_T : public DrawAttributeArrays
3552    {
3553        DrawAttributeArrays_T(osg::Geometry* geometry)
3554        {
3555
3556        }
3557
3558        virtual bool valid() const { return _t1.valid(); }
3559
3560        virtual void set(osg::Geometry* geometry)
3561        {
3562            _t1.set(geometry);
3563        }
3564
3565        virtual unsigned int draw(unsigned int index, unsigned int count) const
3566        {
3567            for(unsigned int i=0;i<count;++i,++index)
3568            {
3569                _t1.draw(index);
3570            }
3571            return index;
3572        }
3573
3574        T1 _t1;
3575    };
3576
3577    template < class T1, class T2 >
3578    struct DrawAttributeArrays_TT : public DrawAttributeArrays
3579    {
3580        DrawAttributeArrays_TT()
3581        {
3582        }
3583
3584        virtual bool valid() const { return _t1.valid() && _t2.valid(); }
3585
3586        virtual void set(osg::Geometry* geometry)
3587        {
3588            _t1.set(geometry);
3589            _t2.set(geometry);
3590        }
3591
3592        virtual unsigned int draw(unsigned int index, unsigned int count) const
3593        {
3594            for(unsigned int i=0;i<count;++i,++index)
3595            {
3596                _t1.draw(index);
3597                _t2.draw(index);
3598            }
3599            return index;
3600        }
3601
3602        T1 _t1;
3603        T1 _t2;
3604    };
3605
3606    template < class T1, class T2, class T3 >
3607    struct DrawAttributeArrays_TTT : public DrawAttributeArrays
3608    {
3609        DrawAttributeArrays_TTT()
3610        {
3611        }
3612
3613        virtual bool valid() const { return _t1.valid() && _t2.valid() && _t3.valid(); }
3614
3615        virtual void set(osg::Geometry* geometry)
3616        {
3617            _t1.set(geometry);
3618            _t2.set(geometry);
3619            _t3.set(geometry);
3620        }
3621
3622        virtual unsigned int draw(unsigned int index, unsigned int count) const
3623        {
3624            for(unsigned int i=0;i<count;++i,++index)
3625            {
3626                _t1.draw(index);
3627                _t2.draw(index);
3628                _t3.draw(index);
3629            }
3630            return index;
3631        }
3632
3633        T1 _t1;
3634        T2 _t2;
3635        T3 _t3;
3636    };
3637
3638    template < class T1, class T2, class T3, class T4 >
3639    struct DrawAttributeArrays_TTTT : public DrawAttributeArrays
3640    {
3641        DrawAttributeArrays_TTTT()
3642        {
3643        }
3644
3645        virtual bool valid() const { return _t1.valid() && _t2.valid() && _t3.valid() && _t4.valid(); }
3646
3647        virtual void set(osg::Geometry* geometry)
3648        {
3649            _t1.set(geometry);
3650            _t2.set(geometry);
3651            _t3.set(geometry);
3652            _t4.set(geometry);
3653        }
3654
3655        virtual unsigned int draw(unsigned int index, unsigned int count) const
3656        {
3657            for(unsigned int i=0;i<count;++i,++index)
3658            {
3659                _t1.draw(index);
3660                _t2.draw(index);
3661                _t3.draw(index);
3662                _t4.draw(index);
3663            }
3664            return index;
3665        }
3666
3667        T1 _t1;
3668        T2 _t2;
3669        T3 _t3;
3670        T4 _t4;
3671    };
3672
3673    template < class T1, class T2 >
3674    struct DrawAttributeArrays_TT_USI : public DrawAttributeArrays
3675    {
3676        DrawAttributeArrays_TT_USI()
3677        {
3678        }
3679
3680        virtual bool valid() const { return _t1.valid() && _t2.valid() && _indices!=0; }
3681
3682        virtual void set(osg::Geometry* geometry)
3683        {
3684            _t1.set(geometry);
3685            _t2.set(geometry);
3686
3687            _indices = 0;
3688            osg::IndexArray* indices = geometry->getVertexIndices();
3689            if (indices && indices->getType()==osg::Array::UShortArrayType)
3690            {
3691                osg::UShortArray* ushort3array = static_cast<osg::UShortArray*>(array);
3692                if (!ushort3array->empty()) _indices = &(ushort3array->front());
3693            }
3694        }
3695
3696        virtual unsigned int draw(unsigned int index, unsigned int count) const
3697        {
3698            for(unsigned int i=0;i<count;++i,++index)
3699            {
3700                unsigned int ivalue = _indices[index];
3701                _t1.draw(ivalue);
3702                _t2.draw(ivalue);
3703            }
3704            return index;
3705        }
3706
3707        T1 _t1;
3708        T2 _t2;
3709    };
3710
3711    template < class T1, class T2, class T3 >
3712    struct DrawAttributeArrays_TTT_USI : public DrawAttributeArrays
3713    {
3714        DrawAttributeArrays_TTT_USI()
3715        {
3716        }
3717
3718        virtual bool valid() const { return _t1.valid() && _t2.valid() && _t3.valid() && _indices!=0; }
3719
3720        virtual void set(osg::Geometry* geometry)
3721        {
3722            _t1.set(geometry);
3723            _t2.set(geometry);
3724            _t3.set(geometry);
3725
3726            _indices = 0;
3727            osg::IndexArray* indices = geometry->getVertexIndices();
3728            if (indices && indices->getType()==osg::Array::UShortArrayType)
3729            {
3730                osg::UShortArray* ushort3array = static_cast<osg::UShortArray*>(array);
3731                if (!ushort3array->empty()) _indices = &(ushort3array->front());
3732            }
3733        }
3734
3735        virtual unsigned int draw(unsigned int index, unsigned int count) const
3736        {
3737            for(unsigned int i=0;i<count;++i,++index)
3738            {
3739                unsigned int ivalue = _indices[index];
3740                _t1.draw(ivalue);
3741                _t2.draw(ivalue);
3742                _t3.draw(ivalue);
3743            }
3744            return index;
3745        }
3746
3747        T1 _t1;
3748        T2 _t2;
3749        T3 _t3;
3750    };
3751
3752    template < class T1, class T2, class T3, class T4 >
3753    struct DrawAttributeArrays_TTTT_USI : public DrawAttributeArrays
3754    {
3755        DrawAttributeArrays_TTTT_USI()
3756        {
3757        }
3758
3759        virtual bool valid() const { return _t1.valid() && _t2.valid() && _t3.valid() && _t4.valid() && _indices!=0; }
3760
3761        virtual void set(osg::Geometry* geometry)
3762        {
3763            _t1.set(geometry);
3764            _t2.set(geometry);
3765            _t3.set(geometry);
3766            _t4.set(geometry);
3767
3768            _indices = 0;
3769            osg::IndexArray* indices = geometry->getVertexIndices();
3770            if (indices && indices->getType()==osg::Array::UShortArrayType)
3771            {
3772                osg::UShortArray* ushort3array = static_cast<osg::UShortArray*>(array);
3773                if (!ushort3array->empty()) _indices = &(ushort3array->front());
3774            }
3775        }
3776
3777        virtual unsigned int draw(unsigned int index, unsigned int count) const
3778        {
3779            for(unsigned int i=0;i<count;++i,++index)
3780            {
3781                unsigned int ivalue = _indices[index];
3782                _t1.draw(ivalue);
3783                _t2.draw(ivalue);
3784                _t3.draw(ivalue);
3785                _t4.draw(ivalue);
3786            }
3787            return index;
3788        }
3789
3790        T1 _t1;
3791        T2 _t2;
3792        T3 _t3;
3793        T4 _t4;
3794    };
3795
3796    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3797
3798
3799    // One attribute x 2
3800
3801    typedef DrawAttributeArrays_T<V3>                    DrawAttributeArrays_V3;
3802    typedef DrawAttributeArrays_T<V3USI>                 DrawAttributeArrays_V3i;
3803
3804    // Two attributes x 15
3805
3806    typedef DrawAttributeArrays_TT<N3,V3>                DrawAttributeArrays_N3V3;
3807    typedef DrawAttributeArrays_TT<N3USI,V3>             DrawAttributeArrays_N3iV3;
3808    typedef DrawAttributeArrays_TT<N3,V3USI>             DrawAttributeArrays_N3V3i;
3809    typedef DrawAttributeArrays_TT<N3USI,V3USI>          DrawAttributeArrays_N3iV3i;
3810
3811    typedef DrawAttributeArrays_TT_USI<N3,V3>            DrawAttributeArrays_N3V3_i;
3812
3813    typedef DrawAttributeArrays_TT<C4,V3>                DrawAttributeArrays_C4V3;
3814    typedef DrawAttributeArrays_TT<C4USI,V3>             DrawAttributeArrays_C4iV3;
3815    typedef DrawAttributeArrays_TT<C4,V3USI>             DrawAttributeArrays_C4V3i;
3816    typedef DrawAttributeArrays_TT<C4USI,V3USI>          DrawAttributeArrays_C4iV3i;
3817
3818    typedef DrawAttributeArrays_TT_USI<C4,V3>            DrawAttributeArrays_C4V3_i;
3819
3820    typedef DrawAttributeArrays_TT<T2,V3>                DrawAttributeArrays_T2V3;
3821    typedef DrawAttributeArrays_TT<T2USI,V3>             DrawAttributeArrays_T2iV3;
3822    typedef DrawAttributeArrays_TT<T2,V3USI>             DrawAttributeArrays_T2V3i;
3823    typedef DrawAttributeArrays_TT<T2USI,V3USI>          DrawAttributeArrays_T2iV3i;
3824
3825    typedef DrawAttributeArrays_TT_USI<T2,V3>            DrawAttributeArrays_T2V3_i;
3826
3827    // Three attributes x 27
3828
3829    typedef DrawAttributeArrays_TTT<C4,N3,V3>            DrawAttributeArrays_C4N3V3;
3830    typedef DrawAttributeArrays_TTT<C4USI,N3,V3>         DrawAttributeArrays_C4iN3V3;
3831    typedef DrawAttributeArrays_TTT<C4,N3USI,V3>         DrawAttributeArrays_C4N3iV3;
3832    typedef DrawAttributeArrays_TTT<C4USI,N3USI,V3>      DrawAttributeArrays_C4iN3iV3;
3833
3834    typedef DrawAttributeArrays_TTT<C4,N3,V3USI>         DrawAttributeArrays_C4N3V3i;
3835    typedef DrawAttributeArrays_TTT<C4USI,N3,V3USI>      DrawAttributeArrays_C4iN3V3i;
3836    typedef DrawAttributeArrays_TTT<C4,N3USI,V3USI>      DrawAttributeArrays_C4N3iV3i;
3837    typedef DrawAttributeArrays_TTT<C4USI,N3USI,V3USI>   DrawAttributeArrays_C4iN3iV3i;
3838
3839    typedef DrawAttributeArrays_TTT_USI<C4,N3,V3>        DrawAttributeArrays_C4N3V3_i;
3840
3841
3842    typedef DrawAttributeArrays_TTT<T2,N3,V3>            DrawAttributeArrays_T2N3V3;
3843    typedef DrawAttributeArrays_TTT<T2USI,N3,V3>         DrawAttributeArrays_T2iN3V3;
3844    typedef DrawAttributeArrays_TTT<T2,N3USI,V3>         DrawAttributeArrays_T2iN3iV3;
3845    typedef DrawAttributeArrays_TTT<T2USI,N3USI,V3>      DrawAttributeArrays_T2N3iV3;
3846
3847    typedef DrawAttributeArrays_TTT<T2,N3,V3USI>         DrawAttributeArrays_T2N3V3i;
3848    typedef DrawAttributeArrays_TTT<T2USI,N3,V3USI>      DrawAttributeArrays_T2iN3V3i;
3849    typedef DrawAttributeArrays_TTT<T2,N3USI,V3USI>      DrawAttributeArrays_T2iN3iV3i;
3850    typedef DrawAttributeArrays_TTT<T2USI,N3USI,V3USI>   DrawAttributeArrays_T2N3iV3i;
3851
3852    typedef DrawAttributeArrays_TTT_USI<T2,N3,V3>        DrawAttributeArrays_T2N3V3_i;
3853
3854
3855
3856    typedef DrawAttributeArrays_TTT<T2,C4,V3>            DrawAttributeArrays_T2C4V3;
3857    typedef DrawAttributeArrays_TTT<T2USI,C4,V3>         DrawAttributeArrays_T2iC4V3;
3858    typedef DrawAttributeArrays_TTT<T2,C4USI,V3>         DrawAttributeArrays_T2C4iV3;
3859    typedef DrawAttributeArrays_TTT<T2USI,C4USI,V3>      DrawAttributeArrays_T2iC4iV3;
3860
3861    typedef DrawAttributeArrays_TTT<T2,C4,V3USI>         DrawAttributeArrays_T2C4V3i;
3862    typedef DrawAttributeArrays_TTT<T2USI,C4,V3USI>      DrawAttributeArrays_T2iC4V3i;
3863    typedef DrawAttributeArrays_TTT<T2,C4USI,V3USI>      DrawAttributeArrays_T2C4iV3i;
3864    typedef DrawAttributeArrays_TTT<T2USI,C4USI,V3USI>   DrawAttributeArrays_T2iC4iV3i;
3865
3866    typedef DrawAttributeArrays_TTT_USI<T2,C4,V3>        DrawAttributeArrays_T2C4V3_t;
3867
3868
3869    // Four attributes x 17
3870
3871    typedef DrawAttributeArrays_TTTT<T2,C4,N3,V3>                DrawAttributeArrays_T2C4N3V3;
3872    typedef DrawAttributeArrays_TTTT<T2USI,C4,N3,V3>             DrawAttributeArrays_T2iC4N3V3;
3873    typedef DrawAttributeArrays_TTTT<T2,C4USI,N3,V3>             DrawAttributeArrays_T2C4iN3V3;
3874    typedef DrawAttributeArrays_TTTT<T2USI,C4USI,N3,V3>          DrawAttributeArrays_T2iC4iN3V3;
3875
3876    typedef DrawAttributeArrays_TTTT<T2,C4,N3USI,V3>             DrawAttributeArrays_T2C4N3iV3;
3877    typedef DrawAttributeArrays_TTTT<T2USI,C4,N3USI,V3>          DrawAttributeArrays_T2iC4N3iV3;
3878    typedef DrawAttributeArrays_TTTT<T2,C4USI,N3USI,V3>           DrawAttributeArrays_T2C4iN3iV3;
3879    typedef DrawAttributeArrays_TTTT<T2USI,C4USI,N3USI,V3>       DrawAttributeArrays_T2iC4iN3iV3;
3880
3881    typedef DrawAttributeArrays_TTTT<T2,C4,N3,V3USI>             DrawAttributeArrays_T2C4N3V3i;
3882    typedef DrawAttributeArrays_TTTT<T2USI,C4,N3,V3USI>          DrawAttributeArrays_T2iC4N3V3i;
3883    typedef DrawAttributeArrays_TTTT<T2,C4USI,N3,V3USI>          DrawAttributeArrays_T2C4iN3V3i;
3884    typedef DrawAttributeArrays_TTTT<T2USI,C4USI,N3,V3USI>       DrawAttributeArrays_T2iC4iN3V3i;
3885
3886    typedef DrawAttributeArrays_TTTT<T2,C4,N3USI,V3USI>          DrawAttributeArrays_T2C4N3iV3i;
3887    typedef DrawAttributeArrays_TTTT<T2USI,C4,N3USI,V3USI>       DrawAttributeArrays_T2iC4N3iV3i;
3888    typedef DrawAttributeArrays_TTTT<T2,C4USI,N3USI,V3USI>       DrawAttributeArrays_T2C4iN3iV3i;
3889    typedef DrawAttributeArrays_TTTT<T2USI,C4USI,N3USI,V3USI>    DrawAttributeArrays_T2iC4iN3iV3i;
3890
3891    typedef DrawAttributeArrays_TTTT_USI<T2,C4,N3,V3>            DrawAttributeArrays_T2C4N3V3_i;
3892
3893    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3894
3895
3896#endif
Note: See TracBrowser for help on using the browser.