root/OpenSceneGraph/branches/OpenSceneGraph-2.8/src/osg/Geometry.cpp @ 11208

Revision 11208, 142.2 kB (checked in by paulmartz, 4 years ago)

Merge 10664 to 2.8 branch (MSFBO workaround for OS X).

  • Property svn:mergeinfo set to
    /OpenSceneGraph/branches/OpenSceneGraph-2.8.2/src/osg/Geometry.cpp:10664
    /OpenSceneGraph/trunk/include/osg/src/osg/Geometry.cpp:9882
    /OpenSceneGraph/trunk/src/osg/Geometry.cpp:9900
  • 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    osg::VertexBufferObject* vbo = 0;
1093
1094    ArrayList::iterator vitr;
1095    for(vitr = arrayList.begin();
1096        vitr != arrayList.end() && !vbo;
1097        ++vitr)
1098    {
1099        osg::Array* array = *vitr;
1100        if (array->getVertexBufferObject()) vbo = array->getVertexBufferObject();
1101    }
1102
1103    if (!vbo) vbo = new osg::VertexBufferObject;
1104   
1105    return vbo;
1106}
1107
1108osg::ElementBufferObject* Geometry::getOrCreateElementBufferObject()
1109{
1110    DrawElementsList drawElementsList;
1111    getDrawElementsList(drawElementsList);
1112
1113    osg::ElementBufferObject* ebo = 0;
1114
1115    DrawElementsList::iterator deitr;
1116    for(deitr = drawElementsList.begin();
1117        deitr != drawElementsList.end();
1118        ++deitr)
1119    {
1120        osg::DrawElements* elements = *deitr;
1121        if (!elements->getElementBufferObject()) ebo = elements->getElementBufferObject();
1122    }
1123
1124    if (!ebo) ebo = new osg::ElementBufferObject;
1125   
1126    return ebo;
1127}
1128
1129void Geometry::setUseVertexBufferObjects(bool flag)
1130{
1131    // flag = true;
1132   
1133    // osg::notify(osg::NOTICE)<<"Geometry::setUseVertexBufferObjects("<<flag<<")"<<std::endl;
1134
1135    if (_useVertexBufferObjects==flag) return;
1136
1137    Drawable::setUseVertexBufferObjects(flag);
1138   
1139    ArrayList arrayList;
1140    getArrayList(arrayList);
1141
1142    DrawElementsList drawElementsList;
1143    getDrawElementsList(drawElementsList);
1144
1145    typedef std::vector<osg::VertexBufferObject*>  VertexBufferObjectList;
1146    typedef std::vector<osg::ElementBufferObject*>  ElementBufferObjectList;
1147
1148    if (_useVertexBufferObjects)
1149    {
1150        if (!arrayList.empty())
1151        {
1152
1153            VertexBufferObjectList vboList;
1154           
1155            osg::VertexBufferObject* vbo = 0;
1156
1157            ArrayList::iterator vitr;
1158            for(vitr = arrayList.begin();
1159                vitr != arrayList.end() && !vbo;
1160                ++vitr)
1161            {
1162                osg::Array* array = *vitr;
1163                if (array->getVertexBufferObject()) vbo = array->getVertexBufferObject();
1164            }
1165
1166            if (!vbo) vbo = new osg::VertexBufferObject;
1167
1168            for(vitr = arrayList.begin();
1169                vitr != arrayList.end();
1170                ++vitr)
1171            {
1172                osg::Array* array = *vitr;
1173                if (!array->getVertexBufferObject()) array->setVertexBufferObject(vbo);
1174            }
1175        }
1176
1177        if (!drawElementsList.empty())
1178        {
1179            ElementBufferObjectList eboList;
1180           
1181            osg::ElementBufferObject* ebo = 0;
1182
1183            DrawElementsList::iterator deitr;
1184            for(deitr = drawElementsList.begin();
1185                deitr != drawElementsList.end();
1186                ++deitr)
1187            {
1188                osg::DrawElements* elements = *deitr;
1189                if (elements->getElementBufferObject()) ebo = elements->getElementBufferObject();
1190            }
1191
1192            if (!ebo) ebo = new osg::ElementBufferObject;
1193
1194            for(deitr = drawElementsList.begin();
1195                deitr != drawElementsList.end();
1196                ++deitr)
1197            {
1198                osg::DrawElements* elements = *deitr;
1199                if (!elements->getElementBufferObject()) elements->setElementBufferObject(ebo);
1200            }
1201        }
1202    }
1203    else
1204    {
1205        for(ArrayList::iterator vitr = arrayList.begin();
1206            vitr != arrayList.end();
1207            ++vitr)
1208        {
1209            osg::Array* array = *vitr;
1210            if (array->getVertexBufferObject()) array->setVertexBufferObject(0);
1211        }
1212
1213        for(DrawElementsList::iterator deitr = drawElementsList.begin();
1214            deitr != drawElementsList.end();
1215            ++deitr)
1216        {
1217            osg::DrawElements* elements = *deitr;
1218            if (elements->getElementBufferObject()) elements->setElementBufferObject(0);
1219        }
1220    }
1221}
1222
1223void Geometry::dirtyDisplayList()
1224{
1225    Drawable::dirtyDisplayList();
1226}
1227
1228void Geometry::resizeGLObjectBuffers(unsigned int maxSize)
1229{
1230    Drawable::resizeGLObjectBuffers(maxSize);
1231
1232    ArrayList arrays;
1233    if (getArrayList(arrays))
1234    {
1235        for(ArrayList::iterator itr = arrays.begin();
1236            itr != arrays.end();
1237            ++itr)
1238        {
1239            (*itr)->resizeGLObjectBuffers(maxSize);
1240        }
1241    }
1242
1243    DrawElementsList drawElements;
1244    if (getDrawElementsList(drawElements))
1245    {
1246        for(DrawElementsList::iterator itr = drawElements.begin();
1247            itr != drawElements.end();
1248            ++itr)
1249        {
1250            (*itr)->resizeGLObjectBuffers(maxSize);
1251        }
1252    }
1253}
1254
1255void Geometry::releaseGLObjects(State* state) const
1256{
1257    Drawable::releaseGLObjects(state);
1258
1259    ArrayList arrays;
1260    if (getArrayList(arrays))
1261    {
1262        for(ArrayList::iterator itr = arrays.begin();
1263            itr != arrays.end();
1264            ++itr)
1265        {
1266            (*itr)->releaseGLObjects(state);
1267        }
1268    }
1269
1270    DrawElementsList drawElements;
1271    if (getDrawElementsList(drawElements))
1272    {
1273        for(DrawElementsList::iterator itr = drawElements.begin();
1274            itr != drawElements.end();
1275            ++itr)
1276        {
1277            (*itr)->releaseGLObjects(state);
1278        }
1279    }
1280
1281}
1282
1283void Geometry::drawImplementation(RenderInfo& renderInfo) const
1284{
1285    State& state = *renderInfo.getState();
1286
1287//    unsigned int contextID = state.getContextID();
1288   
1289    // osg::notify(osg::NOTICE)<<"Geometry::drawImplementation"<<std::endl;
1290
1291    if (_internalOptimizedGeometry.valid())
1292    {
1293        _internalOptimizedGeometry->drawImplementation(renderInfo);
1294        return;
1295    }
1296
1297    const Extensions* extensions = getExtensions(state.getContextID(),true);
1298
1299    if( !( ( _vertexData.array.valid() && _vertexData.array->getNumElements() != 0 ) ||
1300           ( _vertexAttribList.size() > 0 &&
1301             _vertexAttribList[0].array.valid() &&
1302             _vertexAttribList[0].array->getNumElements() != 0 ) ) )
1303    {
1304        return;
1305    }
1306
1307    if( ( _vertexData.indices.valid() && _vertexData.indices->getNumElements() == 0 ) ||
1308          ( _vertexAttribList.size() > 0 &&
1309          _vertexAttribList[0].indices.valid() &&
1310          _vertexAttribList[0].indices->getNumElements() == 0 ) )
1311    {
1312        return;
1313    }
1314
1315    DrawNormal         drawNormal(_normalData.array.get(),_normalData.indices.get());
1316    DrawColor          drawColor(_colorData.array.get(),_colorData.indices.get());
1317    DrawSecondaryColor drawSecondaryColor(_secondaryColorData.array.get(),_secondaryColorData.indices.get(),extensions);
1318
1319    DrawFogCoord       drawFogCoord(_fogCoordData.array.get(),_fogCoordData.indices.get(),extensions);
1320
1321
1322    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1323    //
1324    // Set up secondary color if required.
1325    //
1326    AttributeBinding secondaryColorBinding = _secondaryColorData.binding;
1327    if (secondaryColorBinding!=BIND_OFF && !extensions->isSecondaryColorSupported())
1328    {
1329        // switch off if not supported or have a valid data.
1330        secondaryColorBinding = BIND_OFF;
1331    }
1332
1333   
1334    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1335    //
1336    // Set up fog coord if required.
1337    //
1338    AttributeBinding fogCoordBinding = _fogCoordData.binding;
1339    if (fogCoordBinding!=BIND_OFF && !extensions->isFogCoordSupported())
1340    {
1341        // switch off if not supported or have a valid data.
1342        fogCoordBinding = BIND_OFF;
1343    }
1344
1345    unsigned int normalIndex = 0;
1346    unsigned int colorIndex = 0;
1347    unsigned int secondaryColorIndex = 0;
1348    unsigned int fogCoordIndex = 0;
1349
1350#if USE_DEFAULT_NORMAL
1351    // if no values are defined for normal and color provide some defaults...
1352    if (_normalData.binding==BIND_OFF) glNormal3f(0.0f,0.0f,1.0f);
1353#endif
1354
1355#if USE_DEFAULT_COLOUR
1356    if (_colorData.binding==BIND_OFF) glColor4f(1.0f,1.0f,1.0f,1.0f);
1357#endif
1358
1359    typedef std::vector< ref_ptr<DrawVertexAttrib> > DrawVertexAttribList;
1360    typedef std::map< Geometry::AttributeBinding, DrawVertexAttribList> DrawVertexAttribMap;
1361    DrawVertexAttribMap drawVertexAttribMap;
1362   
1363    bool vertexVertexAttributesSupported = extensions->isVertexProgramSupported();
1364    bool handleVertexAttributes = (!_vertexAttribList.empty() && vertexVertexAttributesSupported);
1365
1366    bool usingVertexBufferObjects = _useVertexBufferObjects && state.isVertexBufferObjectSupported();
1367   
1368    if (areFastPathsUsed())
1369    {
1370   
1371        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1372        //
1373        // fast path.       
1374        //
1375        if (usingVertexBufferObjects)
1376        {
1377
1378            //
1379            // Vertex Buffer Object path for defining vertex arrays.
1380            //
1381            state.setNormalPointer(_normalData.binding==BIND_PER_VERTEX ? _normalData.array.get() : 0);
1382            state.setColorPointer(_colorData.binding==BIND_PER_VERTEX ? _colorData.array.get() : 0);
1383            state.setSecondaryColorPointer(_secondaryColorData.binding==BIND_PER_VERTEX ? _secondaryColorData.array.get() : 0);
1384            state.setFogCoordPointer(_fogCoordData.binding==BIND_PER_VERTEX ? _fogCoordData.array.get() : 0);
1385
1386            unsigned int unit;
1387            for(unit=0;unit<_texCoordList.size();++unit)
1388            {
1389                state.setTexCoordPointer(unit, _texCoordList[unit].array.get());
1390            }
1391            state.disableTexCoordPointersAboveAndIncluding(unit);
1392
1393            if( handleVertexAttributes )
1394            {
1395                unsigned int index;
1396                for( index = 0; index < _vertexAttribList.size(); ++index )
1397                {
1398                    const Array* array = _vertexAttribList[index].array.get();
1399                    const AttributeBinding ab = _vertexAttribList[index].binding;
1400                    state.setVertexAttribPointer(index, (ab==BIND_PER_VERTEX ? array : 0), _vertexAttribList[index].normalize);
1401
1402                    if(array && ab!=BIND_PER_VERTEX)
1403                    {
1404                        const IndexArray* indexArray = _vertexAttribList[index].indices.get();
1405
1406                        if( indexArray && indexArray->getNumElements() > 0 )
1407                        {
1408                            drawVertexAttribMap[ab].push_back(
1409                                new DrawVertexAttrib(extensions,index,_vertexAttribList[index].normalize,array,indexArray) );
1410                        }
1411                        else
1412                        {
1413                            drawVertexAttribMap[ab].push_back(
1414                                new DrawVertexAttrib(extensions,index,_vertexAttribList[index].normalize,array,0) );
1415                        }
1416                    }
1417                }
1418                state.disableVertexAttribPointersAboveAndIncluding( index );
1419               
1420            }
1421            else if (vertexVertexAttributesSupported)
1422            {
1423                state.disableVertexAttribPointersAboveAndIncluding( 0 );
1424            }
1425
1426            state.setVertexPointer(_vertexData.array.get());
1427
1428
1429        }
1430        else
1431        {
1432            //std::cout << "none VertexBuffer path"<<std::endl;
1433
1434            //
1435            // Non Vertex Buffer Object path for defining vertex arrays.
1436            //           
1437            if( _vertexData.array.valid() )
1438                state.setVertexPointer(_vertexData.array->getDataSize(),_vertexData.array->getDataType(),0,_vertexData.array->getDataPointer());
1439            else
1440                state.disableVertexPointer();
1441
1442            if (_normalData.binding==BIND_PER_VERTEX && _normalData.array.valid())
1443                state.setNormalPointer(_normalData.array->getDataType(),0,_normalData.array->getDataPointer());
1444            else
1445                state.disableNormalPointer();
1446
1447            if (_colorData.binding==BIND_PER_VERTEX && _colorData.array.valid())
1448                state.setColorPointer(_colorData.array->getDataSize(),_colorData.array->getDataType(),0,_colorData.array->getDataPointer());
1449            else
1450                state.disableColorPointer();
1451
1452            if (secondaryColorBinding==BIND_PER_VERTEX && _secondaryColorData.array.valid())
1453                state.setSecondaryColorPointer(_secondaryColorData.array->getDataSize(),_secondaryColorData.array->getDataType(),0,_secondaryColorData.array->getDataPointer());
1454            else
1455                state.disableSecondaryColorPointer();
1456
1457            if (fogCoordBinding==BIND_PER_VERTEX && _fogCoordData.array.valid())
1458                state.setFogCoordPointer(GL_FLOAT,0,_fogCoordData.array->getDataPointer());
1459            else
1460                state.disableFogCoordPointer();
1461
1462            unsigned int unit;
1463            for(unit=0;unit<_texCoordList.size();++unit)
1464            {
1465                const Array* array = _texCoordList[unit].array.get();
1466                if (array)
1467                    state.setTexCoordPointer(unit,array->getDataSize(),array->getDataType(),0,array->getDataPointer());
1468                else
1469                    state.disableTexCoordPointer(unit);
1470            }
1471            state.disableTexCoordPointersAboveAndIncluding(unit);
1472
1473            if( handleVertexAttributes )
1474            {
1475                unsigned int index;
1476                for( index = 0; index < _vertexAttribList.size(); ++index )
1477                {
1478                    const Array* array = _vertexAttribList[index].array.get();
1479                    const AttributeBinding ab = _vertexAttribList[index].binding;
1480
1481                    if( ab == BIND_PER_VERTEX && array )
1482                    {
1483                        state.setVertexAttribPointer( index, array->getDataSize(), array->getDataType(),
1484                            _vertexAttribList[index].normalize, 0, array->getDataPointer() );
1485                    }
1486                    else
1487                    {
1488                        if( array )
1489                        {
1490                            const IndexArray* indexArray = _vertexAttribList[index].indices.get();
1491
1492                            if( indexArray && indexArray->getNumElements() > 0 )
1493                            {
1494                                drawVertexAttribMap[ab].push_back(
1495                                    new DrawVertexAttrib(extensions,index,_vertexAttribList[index].normalize,array,indexArray) );
1496                            }
1497                            else
1498                            {
1499                                drawVertexAttribMap[ab].push_back(
1500                                    new DrawVertexAttrib(extensions,index,_vertexAttribList[index].normalize,array,0) );
1501                            }
1502                        }
1503
1504                        state.disableVertexAttribPointer( index );
1505                    }
1506                }
1507                state.disableVertexAttribPointersAboveAndIncluding( index );
1508               
1509            }
1510            else if (vertexVertexAttributesSupported)
1511            {
1512                state.disableVertexAttribPointersAboveAndIncluding( 0 );
1513            }
1514        }
1515       
1516        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1517        //
1518        // pass the overall binding values onto OpenGL.
1519        //
1520        if (_normalData.binding==BIND_OVERALL)      drawNormal(normalIndex++);
1521        if (_colorData.binding==BIND_OVERALL)       drawColor(colorIndex++);
1522        if (secondaryColorBinding==BIND_OVERALL)    drawSecondaryColor(secondaryColorIndex++);
1523        if (fogCoordBinding==BIND_OVERALL)          drawFogCoord(fogCoordIndex++);
1524        if (handleVertexAttributes)
1525        {
1526            DrawVertexAttribList &list = drawVertexAttribMap[BIND_OVERALL];
1527
1528            for( unsigned int i = 0; i < list.size(); ++i )
1529            {
1530                list[i]->applyAndIncrement();
1531            }
1532        }
1533
1534        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1535        //
1536        // draw the primitives themselves.
1537        //
1538        for(PrimitiveSetList::const_iterator itr=_primitives.begin();
1539            itr!=_primitives.end();
1540            ++itr)
1541        {
1542
1543            if (_normalData.binding==BIND_PER_PRIMITIVE_SET)      drawNormal(normalIndex++);
1544            if (_colorData.binding==BIND_PER_PRIMITIVE_SET)       drawColor(colorIndex++);
1545            if (secondaryColorBinding==BIND_PER_PRIMITIVE_SET)    drawSecondaryColor(secondaryColorIndex++);
1546            if (fogCoordBinding==BIND_PER_PRIMITIVE_SET)          drawFogCoord(fogCoordIndex++);
1547            if (handleVertexAttributes)
1548            {
1549                DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE_SET];
1550
1551                for( unsigned int i = 0; i < list.size(); ++i )
1552                {
1553                    list[i]->applyAndIncrement();
1554                }
1555            }
1556
1557            (*itr)->draw(state, usingVertexBufferObjects);
1558
1559        }
1560
1561        if (usingVertexBufferObjects)
1562        {
1563#if 1
1564            state.unbindVertexBufferObject();
1565            state.unbindElementBufferObject();
1566#endif
1567        }
1568
1569    }
1570    else
1571    {   
1572
1573        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1574        //
1575        // slow path.       
1576        //
1577       
1578
1579        typedef std::vector< ref_ptr<DrawMultiTexCoord> > DrawTexCoordList;
1580        DrawTexCoordList drawTexCoordList;
1581        drawTexCoordList.reserve(_texCoordList.size());
1582
1583        // fallback if multitexturing not supported.
1584        ref_ptr<DrawTexCoord> drawTextCoord;
1585
1586        if (extensions->isMultiTexSupported() && _texCoordList.size()>1)
1587        {
1588            // multitexture supported..
1589            for(unsigned int unit=0;unit!=_texCoordList.size();++unit)
1590            {
1591                const ArrayData& texcoordData = _texCoordList[unit];
1592                if (texcoordData.array.valid() && texcoordData.array->getNumElements()>0)
1593                {
1594                    if (texcoordData.indices.valid() && texcoordData.indices->getNumElements()>0)
1595                    {
1596                        drawTexCoordList.push_back(new DrawMultiTexCoord(GL_TEXTURE0+unit,texcoordData.array.get(),texcoordData.indices.get(),
1597                                                                         extensions));
1598                    }
1599                    else
1600                    {
1601                        drawTexCoordList.push_back(new DrawMultiTexCoord(GL_TEXTURE0+unit,texcoordData.array.get(),0,
1602                                                                          extensions));
1603                    }
1604                }
1605            }
1606        }
1607        else
1608        {
1609            if (!_texCoordList.empty())
1610            {
1611                const ArrayData& texcoordData = _texCoordList[0];
1612                if (texcoordData.array.valid() && texcoordData.array->getNumElements()>0)
1613                {
1614                    if (texcoordData.indices.valid())
1615                    {
1616                        if (texcoordData.indices->getNumElements()>0)
1617                        {
1618                            drawTextCoord = new DrawTexCoord(texcoordData.array.get(),texcoordData.indices.get());
1619                        }
1620                    }
1621                    else
1622                    {
1623                        drawTextCoord = new DrawTexCoord(texcoordData.array.get(),0);
1624                    }
1625                }
1626            }
1627        }
1628
1629        if(handleVertexAttributes)
1630        {
1631            unsigned int index;
1632            for( index = 1; index < _vertexAttribList.size(); ++index )
1633            {
1634                const ArrayData& vertAttribData = _vertexAttribList[index];
1635           
1636                if( vertAttribData.array.valid() && vertAttribData.array->getNumElements() > 0 )
1637                {
1638                    if( vertAttribData.indices.valid() && vertAttribData.indices->getNumElements() > 0 )
1639                    {
1640                        drawVertexAttribMap[vertAttribData.binding].push_back(
1641                            new DrawVertexAttrib(extensions,index,vertAttribData.normalize,vertAttribData.array.get(),vertAttribData.indices.get() ));
1642                    }
1643                    else
1644                    {
1645                        drawVertexAttribMap[vertAttribData.binding].push_back(
1646                            new DrawVertexAttrib(extensions,index,vertAttribData.normalize,vertAttribData.array.get(),0) );
1647                    }           
1648                }
1649            }
1650        }
1651
1652        // disable all the vertex arrays in the slow path as we are
1653        // sending everything using glVertex etc.
1654        state.disableAllVertexArrays();
1655
1656
1657        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1658        //
1659        // pass the overall binding values onto OpenGL.
1660        //
1661        if (_normalData.binding==BIND_OVERALL)      drawNormal(normalIndex++);
1662        if (_colorData.binding==BIND_OVERALL)       drawColor(colorIndex++);
1663        if (secondaryColorBinding==BIND_OVERALL)    drawSecondaryColor(secondaryColorIndex++);
1664        if (fogCoordBinding==BIND_OVERALL)          drawFogCoord(fogCoordIndex++);
1665        if (handleVertexAttributes)
1666        {
1667            DrawVertexAttribList &list = drawVertexAttribMap[BIND_OVERALL];
1668
1669            for( unsigned int i = 0; i < list.size(); ++i )
1670            {
1671                list[i]->applyAndIncrement();
1672            }
1673        }
1674
1675        // set up vertex functor.
1676        DrawVertex drawVertex(_vertexData.array.get(),_vertexData.indices.get());
1677
1678        bool useVertexAttrib =  _vertexAttribList.size() > 0 &&
1679                                _vertexAttribList[0].array.valid() &&
1680                                 _vertexAttribList[0].indices->getNumElements();
1681
1682        ref_ptr<DrawVertexAttrib> drawVertexAttribZero;
1683        if( useVertexAttrib )
1684        {
1685            drawVertexAttribZero = new DrawVertexAttrib(extensions,0,
1686                _vertexAttribList[0].normalize,_vertexAttribList[0].array.get(),
1687                _vertexAttribList[0].indices.get());
1688        }
1689
1690        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1691        //
1692        // draw the primitives themselves.
1693        //
1694        for(PrimitiveSetList::const_iterator itr=_primitives.begin();
1695            itr!=_primitives.end();
1696            ++itr)
1697        {
1698            if (_normalData.binding==BIND_PER_PRIMITIVE_SET)           drawNormal(normalIndex++);
1699            if (_colorData.binding==BIND_PER_PRIMITIVE_SET)            drawColor(colorIndex++);
1700            if (secondaryColorBinding==BIND_PER_PRIMITIVE_SET)    drawSecondaryColor(secondaryColorIndex++);
1701            if (fogCoordBinding==BIND_PER_PRIMITIVE_SET)          drawFogCoord(fogCoordIndex++);
1702            if (handleVertexAttributes)
1703            {
1704                DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE_SET];
1705
1706                for( unsigned int i = 0; i < list.size(); ++i )
1707                {
1708                    list[i]->applyAndIncrement();
1709                }
1710            }
1711
1712            const PrimitiveSet* primitiveset = itr->get();
1713            GLenum mode=primitiveset->getMode();
1714
1715            unsigned int primLength;
1716            switch(mode)
1717            {
1718                case(GL_POINTS):    primLength=1; break;
1719                case(GL_LINES):     primLength=2; break;
1720                case(GL_TRIANGLES): primLength=3; break;
1721                case(GL_QUADS):     primLength=4; break;
1722                default:            primLength=0; break; // compute later when =0.
1723            }
1724
1725
1726            // draw primitives by the more flexible "slow" path,
1727            // sending OpenGL glBegin/glVertex.../glEnd().
1728            switch(primitiveset->getType())
1729            {
1730                case(PrimitiveSet::DrawArraysPrimitiveType):
1731                {
1732                    if (primLength==0) primLength=primitiveset->getNumIndices();
1733
1734                    const DrawArrays* drawArray = static_cast<const DrawArrays*>(primitiveset);
1735                    glBegin(mode);
1736
1737                    unsigned int primCount=0;
1738                    unsigned int indexEnd = drawArray->getFirst()+drawArray->getCount();
1739                    for(unsigned int vindex=drawArray->getFirst();
1740                        vindex<indexEnd;
1741                        ++vindex,++primCount)
1742                    {
1743
1744                        if ((primCount%primLength)==0)
1745                        {
1746                            if (_normalData.binding==BIND_PER_PRIMITIVE)           drawNormal(normalIndex++);
1747                            if (_colorData.binding==BIND_PER_PRIMITIVE)            drawColor(colorIndex++);
1748                            if (secondaryColorBinding==BIND_PER_PRIMITIVE)    drawSecondaryColor(secondaryColorIndex++);
1749                            if (fogCoordBinding==BIND_PER_PRIMITIVE)          drawFogCoord(fogCoordIndex++);
1750                            if (handleVertexAttributes)
1751                            {
1752                                DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE];
1753
1754                                for( unsigned int i = 0; i < list.size(); ++i )
1755                                {
1756                                    list[i]->applyAndIncrement();
1757                                }
1758                            }                       
1759                        }
1760
1761                        if (_normalData.binding==BIND_PER_VERTEX)           drawNormal(vindex);
1762                        if (_colorData.binding==BIND_PER_VERTEX)            drawColor(vindex);
1763                        if (secondaryColorBinding==BIND_PER_VERTEX)    drawSecondaryColor(vindex);
1764                        if (fogCoordBinding==BIND_PER_VERTEX)          drawFogCoord(vindex);
1765                        if (handleVertexAttributes)
1766                        {
1767                            DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX];
1768
1769                            for( unsigned int i = 0; i < list.size(); ++i )
1770                            {
1771                                list[i]->applyAndIncrement();
1772                            }
1773                        } 
1774
1775                        for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin();
1776                            texItr!=drawTexCoordList.end();
1777                            ++texItr)
1778                        {
1779                            (*(*texItr))(vindex);
1780                        }
1781                        if (drawTextCoord.valid()) (*drawTextCoord)(vindex);
1782
1783                        if( useVertexAttrib )
1784                        {
1785                            (*drawVertexAttribZero)(vindex);
1786                        }
1787                        else
1788                        {
1789                            drawVertex(vindex);
1790                        }
1791                    }
1792                   
1793                    glEnd();
1794                    break;
1795                }
1796                case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
1797                {
1798
1799                    const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
1800                    unsigned int vindex=drawArrayLengths->getFirst();
1801                    for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
1802                        primItr!=drawArrayLengths->end();
1803                        ++primItr)
1804                    {
1805                        unsigned int localPrimLength;
1806                        if (primLength==0) localPrimLength=*primItr;
1807                        else localPrimLength=primLength;
1808
1809                        glBegin(mode);
1810
1811                        for(GLsizei primCount=0;primCount<*primItr;++primCount)
1812                        {
1813                            if ((primCount%localPrimLength)==0)
1814                            {
1815                                if (_normalData.binding==BIND_PER_PRIMITIVE)           drawNormal(normalIndex++);
1816                                if (_colorData.binding==BIND_PER_PRIMITIVE)            drawColor(colorIndex++);
1817                                if (secondaryColorBinding==BIND_PER_PRIMITIVE)    drawSecondaryColor(secondaryColorIndex++);
1818                                if (fogCoordBinding==BIND_PER_PRIMITIVE)          drawFogCoord(fogCoordIndex++);
1819                                if (handleVertexAttributes)
1820                                {
1821                                    DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE];
1822
1823                                    for( unsigned int i = 0; i < list.size(); ++i )
1824                                    {
1825                                        list[i]->applyAndIncrement();
1826                                    }
1827                                } 
1828                            }
1829                           
1830                            if (_normalData.binding==BIND_PER_VERTEX)           drawNormal(vindex);
1831                            if (_colorData.binding==BIND_PER_VERTEX)            drawColor(vindex);
1832                            if (secondaryColorBinding==BIND_PER_VERTEX)    drawSecondaryColor(vindex);
1833                            if (fogCoordBinding==BIND_PER_VERTEX)          drawFogCoord(vindex);
1834                            if (handleVertexAttributes)
1835                            {
1836                                DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX];
1837
1838                                for( unsigned int i = 0; i < list.size(); ++i )
1839                                {
1840                                    list[i]->applyAndIncrement();
1841                                }
1842                            } 
1843                            for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin();
1844                                texItr!=drawTexCoordList.end();
1845                                ++texItr)
1846                            {
1847                                (*(*texItr))(vindex);
1848                            }
1849                            if (drawTextCoord.valid()) (*drawTextCoord)(vindex);
1850
1851                            if( useVertexAttrib )
1852                            {
1853                                (*drawVertexAttribZero)(vindex);
1854                            }
1855                            else
1856                            {
1857                                drawVertex(vindex);
1858                            }
1859
1860                            ++vindex;
1861                        }
1862                       
1863                        glEnd();
1864
1865                    }
1866                    break;
1867                }
1868                case(PrimitiveSet::DrawElementsUBytePrimitiveType):
1869                {
1870                    if (primLength==0) primLength=primitiveset->getNumIndices();
1871
1872                    const DrawElementsUByte* drawElements = static_cast<const DrawElementsUByte*>(primitiveset);
1873                    glBegin(mode);
1874
1875                    unsigned int primCount=0;
1876                    for(DrawElementsUByte::const_iterator primItr=drawElements->begin();
1877                        primItr!=drawElements->end();
1878                        ++primCount,++primItr)
1879                    {
1880
1881                        if ((primCount%primLength)==0)
1882                        {
1883                            if (_normalData.binding==BIND_PER_PRIMITIVE)           drawNormal(normalIndex++);
1884                            if (_colorData.binding==BIND_PER_PRIMITIVE)            drawColor(colorIndex++);
1885                            if (secondaryColorBinding==BIND_PER_PRIMITIVE)    drawSecondaryColor(secondaryColorIndex++);
1886                            if (fogCoordBinding==BIND_PER_PRIMITIVE)          drawFogCoord(fogCoordIndex++);
1887                            if (handleVertexAttributes)
1888                            {
1889                                DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE];
1890
1891                                for( unsigned int i = 0; i < list.size(); ++i )
1892                                {
1893                                    list[i]->applyAndIncrement();
1894                                }
1895                            } 
1896                        }
1897                       
1898                        unsigned int vindex=*primItr;
1899
1900                        if (_normalData.binding==BIND_PER_VERTEX)           drawNormal(vindex);
1901                        if (_colorData.binding==BIND_PER_VERTEX)            drawColor(vindex);
1902                        if (secondaryColorBinding==BIND_PER_VERTEX)    drawSecondaryColor(vindex);
1903                        if (fogCoordBinding==BIND_PER_VERTEX)          drawFogCoord(vindex);
1904                        if ( extensions->isVertexProgramSupported() )
1905                        {
1906                            DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX];
1907
1908                            for( unsigned int i = 0; i < list.size(); ++i )
1909                            {
1910                                list[i]->applyAndIncrement();
1911                            }
1912                        } 
1913
1914                        for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin();
1915                            texItr!=drawTexCoordList.end();
1916                            ++texItr)
1917                        {
1918                            (*(*texItr))(vindex);
1919                        }
1920                        if (drawTextCoord.valid()) (*drawTextCoord)(vindex);
1921
1922                        if( useVertexAttrib )
1923                        {
1924                            (*drawVertexAttribZero)(vindex);
1925                        }
1926                        else
1927                        {
1928                            drawVertex(vindex);
1929                        }
1930                    }
1931
1932                    glEnd();
1933                    break;
1934                }
1935                case(PrimitiveSet::DrawElementsUShortPrimitiveType):
1936                {
1937                    if (primLength==0) primLength=primitiveset->getNumIndices();
1938
1939                    const DrawElementsUShort* drawElements = static_cast<const DrawElementsUShort*>(primitiveset);
1940                    glBegin(mode);
1941
1942                    unsigned int primCount=0;
1943                    for(DrawElementsUShort::const_iterator primItr=drawElements->begin();
1944                        primItr!=drawElements->end();
1945                        ++primCount,++primItr)
1946                    {
1947
1948                        if ((primCount%primLength)==0)
1949                        {
1950                            if (_normalData.binding==BIND_PER_PRIMITIVE)           drawNormal(normalIndex++);
1951                            if (_colorData.binding==BIND_PER_PRIMITIVE)            drawColor(colorIndex++);
1952                            if (secondaryColorBinding==BIND_PER_PRIMITIVE)    drawSecondaryColor(secondaryColorIndex++);
1953                            if (fogCoordBinding==BIND_PER_PRIMITIVE)          drawFogCoord(fogCoordIndex++);
1954                            if (handleVertexAttributes)
1955                            {
1956                                DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE];
1957
1958                                for( unsigned int i = 0; i < list.size(); ++i )
1959                                {
1960                                    list[i]->applyAndIncrement();
1961                                }
1962                            } 
1963                        }
1964                       
1965                        unsigned int vindex=*primItr;
1966
1967                        if (_normalData.binding==BIND_PER_VERTEX)           drawNormal(vindex);
1968                        if (_colorData.binding==BIND_PER_VERTEX)            drawColor(vindex);
1969                        if (secondaryColorBinding==BIND_PER_VERTEX)    drawSecondaryColor(vindex);
1970                        if (fogCoordBinding==BIND_PER_VERTEX)          drawFogCoord(vindex);
1971                        if (handleVertexAttributes)
1972                        {
1973                            DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX];
1974
1975                            for( unsigned int i = 0; i < list.size(); ++i )
1976                            {
1977                                list[i]->applyAndIncrement();
1978                            }
1979                        } 
1980
1981                        for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin();
1982                            texItr!=drawTexCoordList.end();
1983                            ++texItr)
1984                        {
1985                            (*(*texItr))(vindex);
1986                        }
1987                        if (drawTextCoord.valid()) (*drawTextCoord)(vindex);
1988
1989                        if( useVertexAttrib )
1990                        {
1991                            (*drawVertexAttribZero)(vindex);
1992                        }
1993                        else
1994                        {
1995                            drawVertex(vindex);
1996                        }
1997                    }
1998
1999                    glEnd();
2000                    break;
2001                }
2002                case(PrimitiveSet::DrawElementsUIntPrimitiveType):
2003                {
2004                    if (primLength==0) primLength=primitiveset->getNumIndices();
2005
2006                    const DrawElementsUInt* drawElements = static_cast<const DrawElementsUInt*>(primitiveset);
2007                    glBegin(mode);
2008
2009                    unsigned int primCount=0;
2010                    for(DrawElementsUInt::const_iterator primItr=drawElements->begin();
2011                        primItr!=drawElements->end();
2012                        ++primCount,++primItr)
2013                    {
2014
2015                        if ((primCount%primLength)==0)
2016                        {
2017                            if (_normalData.binding==BIND_PER_PRIMITIVE)           drawNormal(normalIndex++);
2018                            if (_colorData.binding==BIND_PER_PRIMITIVE)            drawColor(colorIndex++);
2019                            if (secondaryColorBinding==BIND_PER_PRIMITIVE)    drawSecondaryColor(secondaryColorIndex++);
2020                            if (fogCoordBinding==BIND_PER_PRIMITIVE)          drawFogCoord(fogCoordIndex++);
2021                            if ( extensions->isVertexProgramSupported() )
2022                            {
2023                                DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE];
2024
2025                                for( unsigned int i = 0; i < list.size(); ++i )
2026                                {
2027                                    list[i]->applyAndIncrement();
2028                                }
2029                            } 
2030                        }
2031                       
2032                        unsigned int vindex=*primItr;
2033
2034                        if (_normalData.binding==BIND_PER_VERTEX)           drawNormal(vindex);
2035                        if (_colorData.binding==BIND_PER_VERTEX)            drawColor(vindex);
2036                        if (secondaryColorBinding==BIND_PER_VERTEX)    drawSecondaryColor(vindex);
2037                        if (fogCoordBinding==BIND_PER_VERTEX)          drawFogCoord(vindex);
2038                        if ( extensions->isVertexProgramSupported() )
2039                        {
2040                            DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX];
2041
2042                            for( unsigned int i = 0; i < list.size(); ++i )
2043                            {
2044                                list[i]->applyAndIncrement();
2045                            }
2046                        } 
2047
2048                        for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin();
2049                            texItr!=drawTexCoordList.end();
2050                            ++texItr)
2051                        {
2052                            (*(*texItr))(vindex);
2053                        }
2054                        if (drawTextCoord.valid()) (*drawTextCoord)(vindex);
2055
2056                        if( useVertexAttrib )
2057                        {
2058                            (*drawVertexAttribZero)(vindex);
2059                        }
2060                        else
2061                        {
2062                            drawVertex(vindex);
2063                        }
2064                    }
2065
2066                    glEnd();
2067                    break;
2068                }
2069                default:
2070                {
2071                    break;
2072                }
2073            }
2074        }
2075    }
2076
2077}
2078
2079class AttributeFunctorArrayVisitor : public ArrayVisitor
2080{
2081    public:
2082   
2083        AttributeFunctorArrayVisitor(Drawable::AttributeFunctor& af):
2084            _af(af) {}
2085   
2086        virtual ~AttributeFunctorArrayVisitor() {}
2087
2088        virtual void apply(ByteArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2089        virtual void apply(ShortArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2090        virtual void apply(IntArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2091        virtual void apply(UByteArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2092        virtual void apply(UShortArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2093        virtual void apply(UIntArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2094        virtual void apply(Vec4ubArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2095        virtual void apply(FloatArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2096        virtual void apply(Vec2Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2097        virtual void apply(Vec3Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2098        virtual void apply(Vec4Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2099        virtual void apply(DoubleArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2100        virtual void apply(Vec2dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2101        virtual void apply(Vec3dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2102        virtual void apply(Vec4dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2103   
2104   
2105        inline void applyArray(Drawable::AttributeType type,Array* array)
2106        {
2107            if (array)
2108            {
2109                _type = type;
2110                array->accept(*this);
2111            }
2112        }
2113
2114    protected:       
2115       
2116        AttributeFunctorArrayVisitor& operator = (const AttributeFunctorArrayVisitor&) { return *this; }
2117        Drawable::AttributeFunctor&   _af;
2118        Drawable::AttributeType       _type;
2119};
2120
2121void Geometry::accept(AttributeFunctor& af)
2122{
2123    AttributeFunctorArrayVisitor afav(af);
2124
2125    afav.applyArray(VERTICES,_vertexData.array.get());
2126    afav.applyArray(NORMALS,_normalData.array.get());
2127    afav.applyArray(COLORS,_colorData.array.get());
2128    afav.applyArray(SECONDARY_COLORS,_secondaryColorData.array.get());
2129    afav.applyArray(FOG_COORDS,_fogCoordData.array.get());
2130   
2131    for(unsigned unit=0;unit<_texCoordList.size();++unit)
2132    {
2133        afav.applyArray((AttributeType)(TEXTURE_COORDS_0+unit),_texCoordList[unit].array.get());
2134    }
2135
2136    for(unsigned int index=0; index<_vertexAttribList.size(); ++index)
2137    {
2138        afav.applyArray(index,_vertexAttribList[index].array.get());
2139    }
2140}
2141
2142class ConstAttributeFunctorArrayVisitor : public ConstArrayVisitor
2143{
2144    public:
2145   
2146        ConstAttributeFunctorArrayVisitor(Drawable::ConstAttributeFunctor& af):
2147            _af(af) {}
2148   
2149        virtual ~ConstAttributeFunctorArrayVisitor() {}
2150
2151        virtual void apply(const ByteArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2152        virtual void apply(const ShortArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2153        virtual void apply(const IntArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2154        virtual void apply(const UByteArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2155        virtual void apply(const UShortArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2156        virtual void apply(const UIntArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2157        virtual void apply(const Vec4ubArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2158        virtual void apply(const FloatArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2159        virtual void apply(const Vec2Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2160        virtual void apply(const Vec3Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2161        virtual void apply(const Vec4Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2162        virtual void apply(const DoubleArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2163        virtual void apply(const Vec2dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2164        virtual void apply(const Vec3dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2165        virtual void apply(const Vec4dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
2166   
2167   
2168        inline void applyArray(Drawable::AttributeType type,const Array* array)
2169        {
2170            if (array)
2171            {
2172                _type = type;
2173                array->accept(*this);
2174            }
2175        }
2176   
2177protected:
2178
2179        ConstAttributeFunctorArrayVisitor& operator = (const ConstAttributeFunctorArrayVisitor&) { return *this; }
2180
2181        Drawable::ConstAttributeFunctor&    _af;
2182        Drawable::AttributeType             _type;
2183};
2184
2185void Geometry::accept(ConstAttributeFunctor& af) const
2186{
2187    ConstAttributeFunctorArrayVisitor afav(af);
2188   
2189    afav.applyArray(VERTICES,_vertexData.array.get());
2190    afav.applyArray(NORMALS,_normalData.array.get());
2191    afav.applyArray(COLORS,_colorData.array.get());
2192    afav.applyArray(SECONDARY_COLORS,_secondaryColorData.array.get());
2193    afav.applyArray(FOG_COORDS,_fogCoordData.array.get());
2194
2195    for(unsigned unit=0;unit<_texCoordList.size();++unit)
2196    {
2197        afav.applyArray((AttributeType)(TEXTURE_COORDS_0+unit),_texCoordList[unit].array.get());
2198    }
2199
2200    for(unsigned int index=0; index<_vertexAttribList.size(); ++index)
2201    {
2202        afav.applyArray(index,_vertexAttribList[index].array.get());
2203    }
2204}
2205
2206void Geometry::accept(PrimitiveFunctor& functor) const
2207{
2208    if (!_vertexData.array.valid() || _vertexData.array->getNumElements()==0) return;
2209
2210    if (!_vertexData.indices.valid())
2211    {
2212        switch(_vertexData.array->getType())
2213        {
2214        case(Array::Vec2ArrayType):
2215            functor.setVertexArray(_vertexData.array->getNumElements(),static_cast<const Vec2*>(_vertexData.array->getDataPointer()));
2216            break;
2217        case(Array::Vec3ArrayType):
2218            functor.setVertexArray(_vertexData.array->getNumElements(),static_cast<const Vec3*>(_vertexData.array->getDataPointer()));
2219            break;
2220        case(Array::Vec4ArrayType):
2221            functor.setVertexArray(_vertexData.array->getNumElements(),static_cast<const Vec4*>(_vertexData.array->getDataPointer()));
2222            break;
2223        case(Array::Vec2dArrayType):
2224            functor.setVertexArray(_vertexData.array->getNumElements(),static_cast<const Vec2d*>(_vertexData.array->getDataPointer()));
2225            break;
2226        case(Array::Vec3dArrayType):
2227            functor.setVertexArray(_vertexData.array->getNumElements(),static_cast<const Vec3d*>(_vertexData.array->getDataPointer()));
2228            break;
2229        case(Array::Vec4dArrayType):
2230            functor.setVertexArray(_vertexData.array->getNumElements(),static_cast<const Vec4d*>(_vertexData.array->getDataPointer()));
2231            break;
2232        default:
2233            notify(WARN)<<"Warning: Geometry::accept(PrimitiveFunctor&) cannot handle Vertex Array type"<<_vertexData.array->getType()<<std::endl;
2234            return;
2235        }
2236       
2237        for(PrimitiveSetList::const_iterator itr=_primitives.begin();
2238            itr!=_primitives.end();
2239            ++itr)
2240        {
2241            (*itr)->accept(functor);
2242        }
2243    }
2244    else
2245    {
2246        const Vec2* vec2Array = 0;
2247        const Vec3* vec3Array = 0;
2248        const Vec4* vec4Array = 0;
2249        const Vec2d* vec2dArray = 0;
2250        const Vec3d* vec3dArray = 0;
2251        const Vec4d* vec4dArray = 0;
2252        Array::Type type = _vertexData.array->getType();
2253        switch(type)
2254        {
2255        case(Array::Vec2ArrayType):
2256            vec2Array = static_cast<const Vec2*>(_vertexData.array->getDataPointer());
2257            break;
2258        case(Array::Vec3ArrayType):
2259            vec3Array = static_cast<const Vec3*>(_vertexData.array->getDataPointer());
2260            break;
2261        case(Array::Vec4ArrayType):
2262            vec4Array = static_cast<const Vec4*>(_vertexData.array->getDataPointer());
2263            break;
2264        case(Array::Vec2dArrayType):
2265            vec2dArray = static_cast<const Vec2d*>(_vertexData.array->getDataPointer());
2266            break;
2267        case(Array::Vec3dArrayType):
2268            vec3dArray = static_cast<const Vec3d*>(_vertexData.array->getDataPointer());
2269            break;
2270        case(Array::Vec4dArrayType):
2271            vec4dArray = static_cast<const Vec4d*>(_vertexData.array->getDataPointer());
2272            break;
2273        default:
2274            notify(WARN)<<"Warning: Geometry::accept(PrimitiveFunctor&) cannot handle Vertex Array type"<<_vertexData.array->getType()<<std::endl;
2275            return;
2276        }
2277
2278   
2279        for(PrimitiveSetList::const_iterator itr=_primitives.begin();
2280            itr!=_primitives.end();
2281            ++itr)
2282        {
2283            const PrimitiveSet* primitiveset = itr->get();
2284            GLenum mode=primitiveset->getMode();
2285            switch(primitiveset->getType())
2286            {
2287                case(PrimitiveSet::DrawArraysPrimitiveType):
2288                {
2289                    const DrawArrays* drawArray = static_cast<const DrawArrays*>(primitiveset);
2290                    functor.begin(mode);
2291
2292                    unsigned int indexEnd = drawArray->getFirst()+drawArray->getCount();
2293                    for(unsigned int vindex=drawArray->getFirst();
2294                        vindex<indexEnd;
2295                        ++vindex)
2296                    {
2297                        switch(type)
2298                        {
2299                        case(Array::Vec2ArrayType):
2300                            functor.vertex(vec2Array[_vertexData.indices->index(vindex)]);
2301                            break;
2302                        case(Array::Vec3ArrayType):
2303                            functor.vertex(vec3Array[_vertexData.indices->index(vindex)]);
2304                            break;
2305                        case(Array::Vec4ArrayType):
2306                            functor.vertex(vec4Array[_vertexData.indices->index(vindex)]);
2307                            break;
2308                        case(Array::Vec2dArrayType):
2309                            functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]);
2310                            break;
2311                        case(Array::Vec3dArrayType):
2312                            functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]);
2313                            break;
2314                        case(Array::Vec4dArrayType):
2315                            functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]);
2316                            break;
2317                        default:
2318                            break;
2319                        }
2320
2321                    }
2322                   
2323                    functor.end();
2324                    break;
2325                }
2326                case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
2327                {
2328
2329                    const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
2330                    unsigned int vindex=drawArrayLengths->getFirst();
2331                    for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
2332                        primItr!=drawArrayLengths->end();
2333                        ++primItr)
2334                    {
2335
2336                        functor.begin(mode);
2337
2338                        for(GLsizei primCount=0;primCount<*primItr;++primCount)
2339                        {
2340                            switch(type)
2341                            {
2342                            case(Array::Vec2ArrayType):
2343                                functor.vertex(vec2Array[_vertexData.indices->index(vindex)]);
2344                                break;
2345                            case(Array::Vec3ArrayType):
2346                                functor.vertex(vec3Array[_vertexData.indices->index(vindex)]);
2347                                break;
2348                            case(Array::Vec4ArrayType):
2349                                functor.vertex(vec4Array[_vertexData.indices->index(vindex)]);
2350                                break;
2351                            case(Array::Vec2dArrayType):
2352                                functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]);
2353                                break;
2354                            case(Array::Vec3dArrayType):
2355                                functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]);
2356                                break;
2357                            case(Array::Vec4dArrayType):
2358                                functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]);
2359                                break;
2360                            default:
2361                                break;
2362                            }
2363                            ++vindex;
2364                        }
2365                       
2366                        functor.end();
2367
2368                    }
2369                    break;
2370                }
2371                case(PrimitiveSet::DrawElementsUBytePrimitiveType):
2372                {
2373                    const DrawElementsUByte* drawElements = static_cast<const DrawElementsUByte*>(primitiveset);
2374                    functor.begin(mode);
2375
2376                    unsigned int primCount=0;
2377                    for(DrawElementsUByte::const_iterator primItr=drawElements->begin();
2378                        primItr!=drawElements->end();
2379                        ++primCount,++primItr)
2380                    {
2381                        unsigned int vindex=*primItr;
2382                        switch(type)
2383                        {
2384                        case(Array::Vec2ArrayType):
2385                            functor.vertex(vec2Array[_vertexData.indices->index(vindex)]);
2386                            break;
2387                        case(Array::Vec3ArrayType):
2388                            functor.vertex(vec3Array[_vertexData.indices->index(vindex)]);
2389                            break;
2390                        case(Array::Vec4ArrayType):
2391                            functor.vertex(vec4Array[_vertexData.indices->index(vindex)]);
2392                            break;
2393                        case(Array::Vec2dArrayType):
2394                            functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]);
2395                            break;
2396                        case(Array::Vec3dArrayType):
2397                            functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]);
2398                            break;
2399                        case(Array::Vec4dArrayType):
2400                            functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]);
2401                            break;
2402                        default:
2403                            break;
2404                        }
2405                    }
2406
2407                    functor.end();
2408                    break;
2409                }
2410                case(PrimitiveSet::DrawElementsUShortPrimitiveType):
2411                {
2412                    const DrawElementsUShort* drawElements = static_cast<const DrawElementsUShort*>(primitiveset);
2413                    functor.begin(mode);
2414
2415                    for(DrawElementsUShort::const_iterator primItr=drawElements->begin();
2416                        primItr!=drawElements->end();
2417                        ++primItr)
2418                    {
2419                        unsigned int vindex=*primItr;
2420                        switch(type)
2421                        {
2422                        case(Array::Vec2ArrayType):
2423                            functor.vertex(vec2Array[_vertexData.indices->index(vindex)]);
2424                            break;
2425                        case(Array::Vec3ArrayType):
2426                            functor.vertex(vec3Array[_vertexData.indices->index(vindex)]);
2427                            break;
2428                        case(Array::Vec4ArrayType):
2429                            functor.vertex(vec4Array[_vertexData.indices->index(vindex)]);
2430                            break;
2431                        case(Array::Vec2dArrayType):
2432                            functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]);
2433                            break;
2434                        case(Array::Vec3dArrayType):
2435                            functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]);
2436                            break;
2437                        case(Array::Vec4dArrayType):
2438                            functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]);
2439                            break;
2440                        default:
2441                            break;
2442                        }
2443                    }
2444
2445                    functor.end();
2446                    break;
2447                }
2448                case(PrimitiveSet::DrawElementsUIntPrimitiveType):
2449                {
2450                    const DrawElementsUInt* drawElements = static_cast<const DrawElementsUInt*>(primitiveset);
2451                    functor.begin(mode);
2452
2453                    for(DrawElementsUInt::const_iterator primItr=drawElements->begin();
2454                        primItr!=drawElements->end();
2455                        ++primItr)
2456                    {
2457                        unsigned int vindex=*primItr;
2458                        switch(type)
2459                        {
2460                        case(Array::Vec2ArrayType):
2461                            functor.vertex(vec2Array[_vertexData.indices->index(vindex)]);
2462                            break;
2463                        case(Array::Vec3ArrayType):
2464                            functor.vertex(vec3Array[_vertexData.indices->index(vindex)]);
2465                            break;
2466                        case(Array::Vec4ArrayType):
2467                            functor.vertex(vec4Array[_vertexData.indices->index(vindex)]);
2468                            break;
2469                        case(Array::Vec2dArrayType):
2470                            functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]);
2471                            break;
2472                        case(Array::Vec3dArrayType):
2473                            functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]);
2474                            break;
2475                        case(Array::Vec4dArrayType):
2476                            functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]);
2477                            break;
2478                        default:
2479                            break;
2480                        }
2481                    }
2482
2483                    functor.end();
2484                    break;
2485                }
2486                default:
2487                {
2488                    break;
2489                }
2490            }
2491        }
2492    }
2493    return;
2494}
2495
2496void Geometry::accept(PrimitiveIndexFunctor& functor) const
2497{
2498    if (!_vertexData.array.valid() || _vertexData.array->getNumElements()==0) return;
2499
2500    switch(_vertexData.array->getType())
2501    {
2502    case(Array::Vec2ArrayType):
2503        functor.setVertexArray(_vertexData.array->getNumElements(),static_cast<const Vec2*>(_vertexData.array->getDataPointer()));
2504        break;
2505    case(Array::Vec3ArrayType):
2506        functor.setVertexArray(_vertexData.array->getNumElements(),static_cast<const Vec3*>(_vertexData.array->getDataPointer()));
2507        break;
2508    case(Array::Vec4ArrayType):
2509        functor.setVertexArray(_vertexData.array->getNumElements(),static_cast<const Vec4*>(_vertexData.array->getDataPointer()));
2510        break;
2511    case(Array::Vec2dArrayType):
2512        functor.setVertexArray(_vertexData.array->getNumElements(),static_cast<const Vec2d*>(_vertexData.array->getDataPointer()));
2513        break;
2514    case(Array::Vec3dArrayType):
2515        functor.setVertexArray(_vertexData.array->getNumElements(),static_cast<const Vec3d*>(_vertexData.array->getDataPointer()));
2516        break;
2517    case(Array::Vec4dArrayType):
2518        functor.setVertexArray(_vertexData.array->getNumElements(),static_cast<const Vec4d*>(_vertexData.array->getDataPointer()));
2519        break;
2520    default:
2521        notify(WARN)<<"Warning: Geometry::accept(PrimitiveIndexFunctor&) cannot handle Vertex Array type"<<_vertexData.array->getType()<<std::endl;
2522        return;
2523    }
2524
2525    if (!_vertexData.indices.valid())
2526    {
2527        for(PrimitiveSetList::const_iterator itr=_primitives.begin();
2528            itr!=_primitives.end();
2529            ++itr)
2530        {
2531            (*itr)->accept(functor);
2532        }
2533    }
2534    else
2535    {
2536        for(PrimitiveSetList::const_iterator itr=_primitives.begin();
2537            itr!=_primitives.end();
2538            ++itr)
2539        {
2540            const PrimitiveSet* primitiveset = itr->get();
2541            GLenum mode=primitiveset->getMode();
2542            switch(primitiveset->getType())
2543            {
2544                case(PrimitiveSet::DrawArraysPrimitiveType):
2545                {
2546                    const DrawArrays* drawArray = static_cast<const DrawArrays*>(primitiveset);
2547                    functor.begin(mode);
2548
2549                    unsigned int indexEnd = drawArray->getFirst()+drawArray->getCount();
2550                    for(unsigned int vindex=drawArray->getFirst();
2551                        vindex<indexEnd;
2552                        ++vindex)
2553                    {
2554                        functor.vertex(_vertexData.indices->index(vindex));
2555                    }
2556                   
2557                    functor.end();
2558                    break;
2559                }
2560                case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
2561                {
2562
2563                    const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
2564                    unsigned int vindex=drawArrayLengths->getFirst();
2565                    for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
2566                        primItr!=drawArrayLengths->end();
2567                        ++primItr)
2568                    {
2569
2570                        functor.begin(mode);
2571
2572                        for(GLsizei primCount=0;primCount<*primItr;++primCount)
2573                        {
2574                            functor.vertex(_vertexData.indices->index(vindex));
2575                            ++vindex;
2576                        }
2577                       
2578                        functor.end();
2579
2580                    }
2581                    break;
2582                }
2583                case(PrimitiveSet::DrawElementsUBytePrimitiveType):
2584                {
2585                    const DrawElementsUByte* drawElements = static_cast<const DrawElementsUByte*>(primitiveset);
2586                    functor.begin(mode);
2587
2588                    unsigned int primCount=0;
2589                    for(DrawElementsUByte::const_iterator primItr=drawElements->begin();
2590                        primItr!=drawElements->end();
2591                        ++primCount,++primItr)
2592                    {
2593                        unsigned int vindex=*primItr;
2594                        functor.vertex(_vertexData.indices->index(vindex));
2595                    }
2596
2597                    functor.end();
2598                    break;
2599                }
2600                case(PrimitiveSet::DrawElementsUShortPrimitiveType):
2601                {
2602                    const DrawElementsUShort* drawElements = static_cast<const DrawElementsUShort*>(primitiveset);
2603                    functor.begin(mode);
2604
2605                    for(DrawElementsUShort::const_iterator primItr=drawElements->begin();
2606                        primItr!=drawElements->end();
2607                        ++primItr)
2608                    {
2609                        unsigned int vindex=*primItr;
2610                        functor.vertex(_vertexData.indices->index(vindex));
2611                    }
2612
2613                    functor.end();
2614                    break;
2615                }
2616                case(PrimitiveSet::DrawElementsUIntPrimitiveType):
2617                {
2618                    const DrawElementsUInt* drawElements = static_cast<const DrawElementsUInt*>(primitiveset);
2619                    functor.begin(mode);
2620
2621                    for(DrawElementsUInt::const_iterator primItr=drawElements->begin();
2622                        primItr!=drawElements->end();
2623                        ++primItr)
2624                    {
2625                        unsigned int vindex=*primItr;
2626                        functor.vertex(_vertexData.indices->index(vindex));
2627                    }
2628
2629                    functor.end();
2630                    break;
2631                }
2632                default:
2633                {
2634                    break;
2635                }
2636            }
2637        }
2638    }
2639    return;
2640}
2641
2642unsigned int _computeNumberOfPrimitives(const osg::Geometry& geom)
2643{
2644
2645    unsigned int totalNumberOfPrimitives = 0;
2646   
2647    for(Geometry::PrimitiveSetList::const_iterator itr=geom.getPrimitiveSetList().begin();
2648        itr!=geom.getPrimitiveSetList().end();
2649        ++itr)
2650    {
2651        const PrimitiveSet* primitiveset = itr->get();
2652        GLenum mode=primitiveset->getMode();
2653
2654        unsigned int primLength;
2655        switch(mode)
2656        {
2657            case(GL_POINTS):    primLength=1; osg::notify(osg::INFO)<<"prim=GL_POINTS"<<std::endl; break;
2658            case(GL_LINES):     primLength=2; osg::notify(osg::INFO)<<"prim=GL_LINES"<<std::endl; break;
2659            case(GL_TRIANGLES): primLength=3; osg::notify(osg::INFO)<<"prim=GL_TRIANGLES"<<std::endl; break;
2660            case(GL_QUADS):     primLength=4; osg::notify(osg::INFO)<<"prim=GL_QUADS"<<std::endl; break;
2661            default:            primLength=0; osg::notify(osg::INFO)<<"prim="<<std::hex<<mode<<std::dec<<std::endl; break; // compute later when =0.
2662        }
2663
2664        // draw primitives by the more flexible "slow" path,
2665        // sending OpenGL glBegin/glVertex.../glEnd().
2666        switch(primitiveset->getType())
2667        {
2668            case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
2669            {
2670
2671                const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
2672                for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
2673                    primItr!=drawArrayLengths->end();
2674                    ++primItr)
2675                {
2676                    if (primLength==0) totalNumberOfPrimitives += 1;
2677                    else totalNumberOfPrimitives += *primItr/primLength;
2678                }
2679                break;
2680            }
2681            default:
2682            {
2683                if (primLength==0) { totalNumberOfPrimitives += 1; osg::notify(osg::INFO)<<"   totalNumberOfPrimitives="<<totalNumberOfPrimitives<<std::endl;}
2684                else { totalNumberOfPrimitives += primitiveset->getNumIndices()/primLength; osg::notify(osg::INFO)<<"   primitiveset->getNumIndices()="<<primitiveset->getNumIndices()<<" totalNumberOfPrimitives="<<totalNumberOfPrimitives<<std::endl; }
2685
2686            }
2687        }
2688    }
2689
2690    return totalNumberOfPrimitives;
2691}
2692
2693template<class A>
2694bool _verifyBindings(const osg::Geometry& geom, const A& arrayData)
2695{
2696    unsigned int numElements = arrayData.indices.valid()?arrayData.indices->getNumElements():
2697                               arrayData.array.valid()?arrayData.array->getNumElements():0;
2698
2699    switch(arrayData.binding)
2700    {
2701        case(osg::Geometry::BIND_OFF):
2702            if (numElements>0) return false;
2703            break;
2704        case(osg::Geometry::BIND_OVERALL):
2705            if (numElements!=1) return false;
2706            break;
2707        case(osg::Geometry::BIND_PER_PRIMITIVE_SET):
2708            if (numElements!=geom.getPrimitiveSetList().size()) return false;
2709            break;
2710        case(osg::Geometry::BIND_PER_PRIMITIVE):
2711            if (numElements!=_computeNumberOfPrimitives(geom)) return false;
2712            break;
2713        case(osg::Geometry::BIND_PER_VERTEX):
2714        {
2715            unsigned int numVertices = geom.getVertexIndices()?geom.getVertexIndices()->getNumElements():
2716                                       geom.getVertexArray()?geom.getVertexArray()->getNumElements():0;
2717            if (numElements!=numVertices) return false;       
2718            break;
2719        }
2720    }
2721    return true;
2722}
2723
2724template<class A>
2725void _computeCorrectBindingsAndArraySizes(std::ostream& out, const osg::Geometry& geom, A& arrayData, const char* arrayName)
2726{
2727    unsigned int numElements = arrayData.indices.valid()?arrayData.indices->getNumElements():
2728                               arrayData.array.valid()?arrayData.array->getNumElements():0;
2729
2730    // check to see if binding matches 0 elements required.
2731    if (numElements==0)
2732    {
2733        // correct binding if not correct.
2734        if (arrayData.binding!=osg::Geometry::BIND_OFF)
2735        {
2736            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() "<<std::endl
2737                   <<"         "<<arrayName<<" binding has been reset to BIND_OFF"<<std::endl;
2738            arrayData.binding=osg::Geometry::BIND_OFF;
2739        }
2740        return;
2741    }
2742
2743    // check to see if binding matches 1 elements required.
2744    if (numElements==1)
2745    {
2746        // correct binding if not correct.
2747        if (arrayData.binding!=osg::Geometry::BIND_OVERALL)
2748        {
2749            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() "<<std::endl
2750                   <<"         "<<arrayName<<" binding has been reset to BIND_OVERALL"<<std::endl;
2751            arrayData.binding=osg::Geometry::BIND_OVERALL;
2752        }
2753        return;
2754    }
2755
2756
2757    unsigned int numVertices = geom.getVertexIndices()?geom.getVertexIndices()->getNumElements():
2758                               geom.getVertexArray()?geom.getVertexArray()->getNumElements():0;
2759   
2760    if ( numVertices==0 )
2761    {
2762        if (arrayData.binding!=osg::Geometry::BIND_OFF)
2763        {
2764            arrayData.array = 0;
2765            arrayData.indices = 0;
2766            arrayData.binding = osg::Geometry::BIND_OFF;
2767            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() vertex array is empty but "<<std::endl
2768                <<"         vertex array is empty but"<<arrayName<<" is set"<<std::endl
2769                <<"         reseting "<<arrayName<< " binding to BIND_OFF and array & indices to 0."<<std::endl;
2770        }
2771    }
2772   
2773    if (numElements==numVertices)
2774    {
2775        // correct the binding to per vertex.
2776        if (arrayData.binding!=osg::Geometry::BIND_PER_VERTEX)
2777        {
2778            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() "<<std::endl
2779                   <<"         "<<arrayName<<" binding has been reset to BIND_PER_VERTEX"<<std::endl;
2780            arrayData.binding = osg::Geometry::BIND_PER_VERTEX;
2781        }
2782        return;
2783    }
2784
2785
2786
2787    // check to see if binding might be per primitive set   
2788    unsigned int numPrimitiveSets = geom.getPrimitiveSetList().size();
2789   
2790    if (numElements==numPrimitiveSets)
2791    {
2792        if (arrayData.binding != osg::Geometry::BIND_PER_PRIMITIVE_SET)
2793        {
2794            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() "<<std::endl
2795                   <<"         "<<arrayName<<" binding has been reset to BIND_PER_PRIMITIVE_SET"<<std::endl;
2796            arrayData.binding = osg::Geometry::BIND_PER_PRIMITIVE_SET;
2797        }
2798        return;
2799    }
2800   
2801    // check to see if binding might be per primitive   
2802    unsigned int numPrimitives = _computeNumberOfPrimitives(geom);
2803    if (numElements==numPrimitives)
2804    {
2805        if (arrayData.binding != osg::Geometry::BIND_PER_PRIMITIVE)
2806        {
2807            out<<"Warning: in osg::Geometry::computeCorrectBindingsAndArraySizes() "<<std::endl
2808                   <<"         "<<arrayName<<" binding has been reset to BIND_PER_PRIMITIVE"<<std::endl;
2809            arrayData.binding = osg::Geometry::BIND_PER_PRIMITIVE;
2810        }
2811        return;
2812    }
2813
2814    if (numElements>numVertices)
2815    {
2816        arrayData.binding = osg::Geometry::BIND_PER_VERTEX;
2817        return;
2818    }
2819    if (numElements>numPrimitives)
2820    {
2821        arrayData.binding = osg::Geometry::BIND_PER_PRIMITIVE;
2822        return;
2823    }
2824    if (numElements>numPrimitiveSets)
2825    {
2826        arrayData.binding = osg::Geometry::BIND_PER_PRIMITIVE_SET;
2827        return;
2828    }
2829    if (numElements>=1)
2830    {
2831        arrayData.binding = osg::Geometry::BIND_OVERALL;
2832        return;
2833    }
2834    arrayData.binding = osg::Geometry::BIND_OFF;
2835 
2836}       
2837
2838bool Geometry::verifyBindings(const ArrayData& arrayData) const
2839{
2840    return _verifyBindings(*this,arrayData);
2841}
2842
2843bool Geometry::verifyBindings(const Vec3ArrayData& arrayData) const
2844{
2845    return _verifyBindings(*this,arrayData);
2846}
2847
2848void Geometry::computeCorrectBindingsAndArraySizes(ArrayData& arrayData, const char* arrayName)
2849{
2850    _computeCorrectBindingsAndArraySizes(osg::notify(osg::INFO),*this,arrayData,arrayName);
2851}
2852
2853void Geometry::computeCorrectBindingsAndArraySizes(Vec3ArrayData& arrayData, const char* arrayName)
2854{
2855    _computeCorrectBindingsAndArraySizes(osg::notify(osg::INFO),*this,arrayData,arrayName);
2856}
2857
2858bool Geometry::verifyBindings() const
2859{
2860    if (!verifyBindings(_normalData)) return false;
2861    if (!verifyBindings(_colorData)) return false;
2862    if (!verifyBindings(_secondaryColorData)) return false;
2863    if (!verifyBindings(_fogCoordData)) return false;
2864
2865    for(ArrayDataList::const_iterator titr=_texCoordList.begin();
2866        titr!=_texCoordList.end();
2867        ++titr)
2868    {
2869        if (!verifyBindings(*titr)) return false;
2870    }
2871
2872    for(ArrayDataList::const_iterator vitr=_vertexAttribList.begin();
2873        vitr!=_vertexAttribList.end();
2874        ++vitr)
2875    {
2876        if (!verifyBindings(*vitr)) return false;
2877    }
2878
2879    return true;
2880}
2881
2882void Geometry::computeCorrectBindingsAndArraySizes()
2883{
2884    // if (verifyBindings()) return;
2885   
2886    computeCorrectBindingsAndArraySizes(_normalData,"_normalData");
2887    computeCorrectBindingsAndArraySizes(_colorData,"_colorData");
2888    computeCorrectBindingsAndArraySizes(_secondaryColorData,"_secondaryColorData");
2889    computeCorrectBindingsAndArraySizes(_fogCoordData,"_fogCoordData");
2890
2891    for(ArrayDataList::iterator titr=_texCoordList.begin();
2892        titr!=_texCoordList.end();
2893        ++titr)
2894    {
2895        computeCorrectBindingsAndArraySizes(*titr,"_texCoordList[]");
2896    }
2897
2898    for(ArrayDataList::iterator vitr=_vertexAttribList.begin();
2899        vitr!=_vertexAttribList.end();
2900        ++vitr)
2901    {
2902        computeCorrectBindingsAndArraySizes(*vitr,"_vertAttribList[]");
2903    }
2904}
2905
2906class ExpandIndexedArray : public osg::ConstArrayVisitor
2907{
2908    public:
2909        ExpandIndexedArray(const osg::IndexArray& indices,Array* targetArray):
2910            _indices(indices),
2911            _targetArray(targetArray) {}
2912       
2913        virtual ~ExpandIndexedArray() {}
2914
2915        // Create when both of the arrays are predefined templated classes. We
2916        // can do some optimizations in this case that aren't possible in the general
2917        // case.
2918        template <class T,class I>
2919        T* create_inline(const T& array,const I& indices)
2920        {
2921            T* newArray = 0;
2922
2923            // if source array type and target array type are equal but arrays arn't equal
2924            if (_targetArray && _targetArray->getType()==array.getType() && _targetArray!=(osg::Array*)(&array))
2925            {
2926                // reuse exisiting target array
2927                newArray = static_cast<T*>(_targetArray);
2928                if (newArray->size()!=indices.size())
2929                {
2930                    // make sure its the right size
2931                    newArray->resize(indices.size());
2932                }
2933            }
2934            else
2935            {
2936                //  else create a new array.
2937                newArray = new T(indices.size());
2938            }
2939
2940            for(unsigned int i=0;i<indices.size();++i)
2941            {
2942                (*newArray)[i]= array[indices[i]];
2943            }
2944
2945            return newArray;
2946        }
2947
2948        // Create when one of the arrays isn't one of the predefined templated classes. The
2949        // template parameter is the type of the array that will get created. This is  always
2950        // one of the predefined classes. We could call clone to get one of the same type as
2951        // the input array, but the interface of the osg::Array class doesn't include a way
2952        // to set an element.
2953        template <class T>
2954        osg::Array* create_noinline(const osg::Array& array, const osg::IndexArray& indices)
2955        {
2956            T* newArray = 0;
2957            typedef typename T::ElementDataType EDT;
2958
2959            unsigned int num_indices = indices.getNumElements();
2960            newArray = new T(num_indices);
2961
2962            const EDT* src = static_cast<const EDT*>(array.getDataPointer());
2963
2964            for(unsigned int i=0;i<num_indices;++i)
2965            {
2966                (*newArray)[i]= src[indices.index(i)];
2967            }
2968
2969            return newArray;
2970        }
2971
2972        osg::Array* create_noinline(const osg::Array& array, const osg::IndexArray& indices)
2973        {
2974            switch (array.getType())
2975            {
2976                case(osg::Array::ByteArrayType):   return create_noinline<osg::ByteArray>(array,indices);
2977                case(osg::Array::ShortArrayType):  return create_noinline<osg::ShortArray>(array,indices);
2978                case(osg::Array::IntArrayType):    return create_noinline<osg::IntArray>(array,indices);
2979                case(osg::Array::UByteArrayType):  return create_noinline<osg::UByteArray>(array,indices);
2980                case(osg::Array::UShortArrayType): return create_noinline<osg::UShortArray>(array,indices);
2981                case(osg::Array::UIntArrayType):   return create_noinline<osg::UIntArray>(array,indices);
2982                case(osg::Array::Vec4ubArrayType): return create_noinline<osg::Vec4ubArray>(array,indices);
2983                case(osg::Array::FloatArrayType):  return create_noinline<osg::FloatArray>(array,indices);
2984                case(osg::Array::Vec2ArrayType):   return create_noinline<osg::Vec2Array>(array,indices);
2985                case(osg::Array::Vec3ArrayType):   return create_noinline<osg::Vec3Array>(array,indices);
2986                case(osg::Array::Vec4ArrayType):   return create_noinline<osg::Vec4Array>(array,indices);
2987                case(osg::Array::Vec2dArrayType):   return create_noinline<osg::Vec2dArray>(array,indices);
2988                case(osg::Array::Vec3dArrayType):   return create_noinline<osg::Vec3dArray>(array,indices);
2989                case(osg::Array::Vec4dArrayType):   return create_noinline<osg::Vec4dArray>(array,indices);
2990                default:
2991                    return NULL;
2992            }
2993        }
2994
2995        template <class TA, class TI>
2996        osg::Array* create(const TA& array, const osg::IndexArray& indices)
2997        {
2998            // We know that indices.getType returned the same thing as TI, but
2999            // we need to determine whether it is really an instance of TI, or
3000            // perhaps another subclass of osg::Array that contains the same
3001            // type of data.
3002            const TI* ba(dynamic_cast<const TI*>(&indices));
3003            if (ba != NULL) {
3004                return create_inline(array,*ba);
3005            }
3006            else {
3007                return create_noinline(array, _indices);
3008            }
3009        }
3010
3011        template <class T>
3012        osg::Array* create(const T& array)
3013        {
3014            switch(_indices.getType())
3015            {
3016            case(osg::Array::ByteArrayType):   return create<T, osg::ByteArray>(array, _indices);
3017            case(osg::Array::ShortArrayType):  return create<T, osg::ShortArray>(array, _indices);
3018            case(osg::Array::IntArrayType):    return create<T, osg::IntArray>(array, _indices);
3019            case(osg::Array::UByteArrayType):  return create<T, osg::UByteArray>(array, _indices);
3020            case(osg::Array::UShortArrayType): return create<T, osg::UShortArray>(array, _indices);
3021            case(osg::Array::UIntArrayType):   return create<T, osg::UIntArray>(array, _indices);
3022            default:                           return create_noinline(array, _indices);
3023            }
3024           
3025        }
3026
3027        // applys for the predefined classes go through 1-arg create to do indexing
3028        virtual void apply(const osg::ByteArray& array) { _targetArray = create(array); }
3029        virtual void apply(const osg::ShortArray& array) { _targetArray = create(array); }
3030        virtual void apply(const osg::IntArray& array) { _targetArray = create(array); }
3031        virtual void apply(const osg::UByteArray& array) { _targetArray = create(array); }
3032        virtual void apply(const osg::UShortArray& array) { _targetArray = create(array); }
3033        virtual void apply(const osg::UIntArray& array) { _targetArray = create(array); }
3034        virtual void apply(const osg::Vec4ubArray& array) { _targetArray = create(array); }
3035        virtual void apply(const osg::FloatArray& array) { _targetArray = create(array); }
3036        virtual void apply(const osg::Vec2Array& array) { _targetArray = create(array); }
3037        virtual void apply(const osg::Vec3Array& array) { _targetArray = create(array); }
3038        virtual void apply(const osg::Vec4Array& array) { _targetArray = create(array); }
3039
3040        // other subclasses of osg::Array end up here
3041        virtual void apply(const osg::Array& array) { _targetArray = create_noinline(array, _indices); }
3042
3043        const osg::IndexArray& _indices;
3044        osg::Array* _targetArray;
3045
3046    protected:
3047
3048        ExpandIndexedArray& operator = (const ExpandIndexedArray&) { return *this; }
3049
3050};
3051
3052bool Geometry::suitableForOptimization() const
3053{
3054    bool hasIndices = false;
3055
3056    if (getVertexIndices()) hasIndices = true;
3057
3058    if (getNormalIndices()) hasIndices = true;
3059
3060    if (getColorIndices()) hasIndices = true;
3061
3062    if (getSecondaryColorIndices()) hasIndices = true;
3063
3064    if (getFogCoordIndices()) hasIndices = true;
3065
3066    for(unsigned int ti=0;ti<getNumTexCoordArrays();++ti)
3067    {
3068        if (getTexCoordIndices(ti)) hasIndices = true;
3069    }
3070   
3071    for(unsigned int vi=0;vi<getNumVertexAttribArrays();++vi)
3072    {
3073        if (getVertexAttribIndices(vi)) hasIndices = true;
3074    }
3075
3076    return hasIndices;
3077}
3078
3079void Geometry::copyToAndOptimize(Geometry& target)
3080{
3081    bool copyToSelf = (this==&target);
3082
3083    // copy over primitive sets.
3084    if (!copyToSelf) target.getPrimitiveSetList() = getPrimitiveSetList();
3085
3086    // copy over attribute arrays.
3087    if (getVertexIndices() && getVertexArray())
3088    {
3089        ExpandIndexedArray eia(*(getVertexIndices()),target.getVertexArray());
3090        getVertexArray()->accept(eia);
3091
3092        target.setVertexArray(eia._targetArray);
3093        target.setVertexIndices(0);
3094    }
3095    else if (getVertexArray())
3096    {
3097        if (!copyToSelf) target.setVertexArray(getVertexArray());
3098    }
3099
3100    target.setNormalBinding(getNormalBinding());
3101    if (getNormalIndices() && getNormalArray())
3102    {
3103        ExpandIndexedArray eia(*(getNormalIndices()),target.getNormalArray());
3104        getNormalArray()->accept(eia);
3105
3106        target.setNormalArray(dynamic_cast<osg::Vec3Array*>(eia._targetArray));
3107        target.setNormalIndices(0);
3108    }
3109    else if (getNormalArray())
3110    {
3111        if (!copyToSelf) target.setNormalArray(getNormalArray());
3112    }
3113
3114    target.setColorBinding(getColorBinding());
3115    if (getColorIndices() && getColorArray())
3116    {
3117        ExpandIndexedArray eia(*(getColorIndices()),target.getColorArray());
3118        getColorArray()->accept(eia);
3119
3120        target.setColorArray(eia._targetArray);
3121        target.setColorIndices(0);
3122    }
3123    else if (getColorArray())
3124    {
3125        if (!copyToSelf) target.setColorArray(getColorArray());
3126    }
3127
3128    target.setSecondaryColorBinding(getSecondaryColorBinding());
3129    if (getSecondaryColorIndices() && getSecondaryColorArray())
3130    {
3131        ExpandIndexedArray eia(*(getSecondaryColorIndices()),target.getSecondaryColorArray());
3132        getSecondaryColorArray()->accept(eia);
3133
3134        target.setSecondaryColorArray(eia._targetArray);
3135        target.setSecondaryColorIndices(0);
3136    }
3137    else if (getSecondaryColorArray())
3138    {
3139        if (!copyToSelf) target.setSecondaryColorArray(getSecondaryColorArray());
3140    }
3141
3142    target.setFogCoordBinding(getFogCoordBinding());
3143    if (getFogCoordIndices() && getFogCoordArray())
3144    {
3145        ExpandIndexedArray eia(*(getFogCoordIndices()),target.getFogCoordArray());
3146        getFogCoordArray()->accept(eia);
3147
3148        target.setFogCoordArray(eia._targetArray);
3149        target.setFogCoordIndices(0);
3150    }
3151    else if (getFogCoordArray())
3152    {
3153        if (!copyToSelf) target.setFogCoordArray(getFogCoordArray());
3154    }
3155
3156    for(unsigned int ti=0;ti<getNumTexCoordArrays();++ti)
3157    {
3158        if (getTexCoordIndices(ti) && getTexCoordArray(ti))
3159        {
3160            ExpandIndexedArray eia(*(getTexCoordIndices(ti)),target.getTexCoordArray(ti));
3161           
3162            getTexCoordArray(ti)->accept(eia);
3163
3164            target.setTexCoordArray(ti,eia._targetArray);
3165            target.setTexCoordIndices(ti,0);
3166        }
3167        else if (getTexCoordArray(ti))
3168        {
3169            if (!copyToSelf) target.setTexCoordArray(ti,getTexCoordArray(ti));
3170        }
3171    }
3172   
3173    for(unsigned int vi=0;vi<_vertexAttribList.size();++vi)
3174    {
3175        ArrayData& arrayData = _vertexAttribList[vi];
3176        if (arrayData.indices.valid())
3177        {
3178            ExpandIndexedArray eia(*arrayData.indices,target.getVertexAttribArray(vi));
3179            arrayData.array->accept(eia);
3180            target.setVertexAttribData(vi,ArrayData(eia._targetArray, 0, arrayData.binding, arrayData.normalize));
3181        }
3182        else if (arrayData.array.valid())
3183        {
3184            if (!copyToSelf) target.setVertexAttribData(vi,arrayData);
3185        }
3186    }
3187}
3188
3189bool Geometry::containsSharedArrays() const
3190{
3191    unsigned int numSharedArrays = 0;
3192   
3193    if (getVertexArray() && getVertexArray()->referenceCount()>1) ++numSharedArrays;
3194    if (getNormalArray() && getNormalArray()->referenceCount()>1) ++numSharedArrays;
3195    if (getColorArray() && getColorArray()->referenceCount()>1) ++numSharedArrays;
3196    if (getSecondaryColorArray() && getSecondaryColorArray()->referenceCount()>1) ++numSharedArrays;
3197    if (getFogCoordArray() && getFogCoordArray()->referenceCount()>1) ++numSharedArrays;
3198
3199    for(unsigned int ti=0;ti<getNumTexCoordArrays();++ti)
3200    {
3201        if (getTexCoordArray(ti) && getTexCoordArray(ti)->referenceCount()>1) ++numSharedArrays;
3202    }
3203   
3204    for(unsigned int vi=0;vi<_vertexAttribList.size();++vi)
3205    {
3206        const ArrayData& arrayData = _vertexAttribList[vi];
3207        if (arrayData.array.valid() && arrayData.array->referenceCount()>1) ++numSharedArrays;
3208    }
3209    return numSharedArrays!=0;
3210}
3211
3212void Geometry::duplicateSharedArrays()
3213{
3214    #define DUPLICATE_IF_REQUIRED(A) \
3215        if (get##A() && get##A()->referenceCount()>1) \
3216        { \
3217            set##A(dynamic_cast<osg::Array*>(get##A()->clone(osg::CopyOp::DEEP_COPY_ARRAYS))); \
3218        }
3219
3220    DUPLICATE_IF_REQUIRED(VertexArray)
3221    DUPLICATE_IF_REQUIRED(NormalArray)
3222    DUPLICATE_IF_REQUIRED(ColorArray)
3223    DUPLICATE_IF_REQUIRED(SecondaryColorArray)
3224    DUPLICATE_IF_REQUIRED(FogCoordArray)
3225
3226    for(unsigned int ti=0;ti<getNumTexCoordArrays();++ti)
3227    {
3228        if (getTexCoordArray(ti) && getTexCoordArray(ti)->referenceCount()>1)
3229        {
3230            setTexCoordArray(ti, dynamic_cast<osg::Array*>(getTexCoordArray(ti)->clone(osg::CopyOp::DEEP_COPY_ARRAYS)));
3231        }
3232    }
3233   
3234    for(unsigned int vi=0;vi<_vertexAttribList.size();++vi)
3235    {
3236        ArrayData& arrayData = _vertexAttribList[vi];
3237        if (arrayData.array.valid() && arrayData.array->referenceCount()>1)
3238        {
3239            arrayData.array = dynamic_cast<osg::Array*>(arrayData.array->clone(osg::CopyOp::DEEP_COPY_ARRAYS));
3240        }
3241    }
3242}
3243
3244void Geometry::computeInternalOptimizedGeometry()
3245{
3246    if (suitableForOptimization())
3247    {
3248        if (!_internalOptimizedGeometry) _internalOptimizedGeometry = new Geometry;
3249
3250        copyToAndOptimize(*_internalOptimizedGeometry);
3251    }
3252}
3253
3254
3255Geometry* osg::createTexturedQuadGeometry(const Vec3& corner,const Vec3& widthVec,const Vec3& heightVec, float l, float b, float r, float t)
3256{
3257    Geometry* geom = new Geometry;
3258
3259    Vec3Array* coords = new Vec3Array(4);
3260    (*coords)[0] = corner+heightVec;
3261    (*coords)[1] = corner;
3262    (*coords)[2] = corner+widthVec;
3263    (*coords)[3] = corner+widthVec+heightVec;
3264    geom->setVertexArray(coords);
3265
3266    Vec2Array* tcoords = new Vec2Array(4);
3267    (*tcoords)[0].set(l,t);
3268    (*tcoords)[1].set(l,b);
3269    (*tcoords)[2].set(r,b);
3270    (*tcoords)[3].set(r,t);
3271    geom->setTexCoordArray(0,tcoords);
3272
3273    osg::Vec4Array* colours = new osg::Vec4Array(1);
3274    (*colours)[0].set(1.0f,1.0f,1.0,1.0f);
3275    geom->setColorArray(colours);
3276    geom->setColorBinding(Geometry::BIND_OVERALL);
3277
3278    osg::Vec3Array* normals = new osg::Vec3Array(1);
3279    (*normals)[0] = widthVec^heightVec;
3280    (*normals)[0].normalize();
3281    geom->setNormalArray(normals);
3282    geom->setNormalBinding(Geometry::BIND_OVERALL);
3283
3284    geom->addPrimitiveSet(new DrawArrays(PrimitiveSet::QUADS,0,4));
3285   
3286    return geom;
3287}
3288
3289
3290
3291
3292///////////////////////////////////////////////////////////////////////////////////////////////
3293///////////////////////////////////////////////////////////////////////////////////////////////
3294///////////////////////////////////////////////////////////////////////////////////////////////
3295///////////////////////////////////////////////////////////////////////////////////////////////
3296///////////////////////////////////////////////////////////////////////////////////////////////
3297///////////////////////////////////////////////////////////////////////////////////////////////
3298///////////////////////////////////////////////////////////////////////////////////////////////
3299
3300
3301// experimental templated rendering code, please ignore...
3302// will move to osg::Geometry once complete.
3303// Robert Osfield, August 2003.
3304#if 0
3305
3306    struct DrawAttributeArrays
3307    {
3308        virtual bool valid() const = 0;
3309        virtual void set(osg::Geometry* geometry) = 0;
3310        virtual unsigned int draw(unsigned int index, unsigned int count) const = 0;
3311    };
3312
3313    struct V3
3314    {
3315        V3():_array(0) {}
3316
3317        bool valid() const { return _array!=0; }
3318
3319        void set(osg::Geometry* geometry)
3320        {
3321            _array = 0;
3322            osg::Array* array = geometry->getVertexArray();
3323            if (array && array->getType()==osg::Array::Vec3ArrayType)
3324            {
3325                osg::Vec3Array* vec3array = static_cast<osg::Vec3Array*>(array);
3326                if (!vec3array->empty()) _array = &(vec3array->front());
3327            }
3328        }
3329
3330        inline void draw(unsigned int index) const
3331        {
3332            glVertex3fv(_array[index].ptr());
3333        }
3334
3335        osg::Vec3* _array;
3336    };
3337
3338    struct V3USI
3339    {
3340        V3USI():_array(0),_indices(0) {}
3341
3342        bool valid() const { return _array!=0 && _indices!=0; }
3343
3344        void set(osg::Geometry* geometry)
3345        {
3346            _array = 0;
3347            osg::Array* array = geometry->getVertexArray();
3348            if (array && array->getType()==osg::Array::Vec3ArrayType)
3349            {
3350                osg::Vec3Array* vec3array = static_cast<osg::Vec3Array*>(array);
3351                if (!vec3array->empty()) _array = &(vec3array->front());
3352            }
3353
3354            _indices = 0;
3355            osg::IndexArray* indices = geometry->getVertexIndices();
3356            if (indices && indices->getType()==osg::Array::UShortArrayType)
3357            {
3358                osg::UShortArray* ushort3array = static_cast<osg::UShortArray*>(array);
3359                if (!ushort3array->empty()) _indices = &(ushort3array->front());
3360            }
3361        }
3362
3363        inline void draw(unsigned int index) const
3364        {
3365            glVertex3fv(_array[_indices[index]].ptr());
3366        }
3367
3368        osg::Vec3*      _array;
3369        unsigned short* _indices;
3370    };
3371
3372    //////////////////////////////
3373
3374    struct N3
3375    {
3376        N3():_array(0) {}
3377
3378        bool valid() const { return _array!=0; }
3379
3380        void set(osg::Geometry* geometry)
3381        {
3382            _array = 0;
3383            osg::Array* array = geometry->getVertexArray();
3384            if (array && array->getType()==osg::Array::Vec3ArrayType)
3385            {
3386                osg::Vec3Array* vec3array = static_cast<osg::Vec3Array*>(array);
3387                if (!vec3array->empty()) _array = &(vec3array->front());
3388            }
3389        }
3390
3391        inline void draw(unsigned int index) const
3392        {
3393            glNormal3fv(_array[index].ptr());
3394        }
3395
3396        osg::Vec3* _array;
3397    };
3398
3399    struct N3USI
3400    {
3401        N3USI():_array(0),_indices(0) {}
3402
3403        bool valid() const { return _array!=0 && _indices!=0; }
3404
3405        void set(osg::Geometry* geometry)
3406        {
3407            _array = 0;
3408            osg::Array* array = geometry->getVertexArray();
3409            if (array && array->getType()==osg::Array::Vec3ArrayType)
3410            {
3411                osg::Vec3Array* vec3array = static_cast<osg::Vec3Array*>(array);
3412                if (!vec3array->empty()) _array = &(vec3array->front());
3413            }
3414
3415            _indices = 0;
3416            osg::IndexArray* indices = geometry->getVertexIndices();
3417            if (indices && indices->getType()==osg::Array::UShortArrayType)
3418            {
3419                osg::UShortArray* ushortarray = static_cast<osg::UShortArray*>(array);
3420                if (!ushortarray->empty()) _indices = &(ushortarray->front());
3421            }
3422        }
3423
3424        inline void draw(unsigned int index) const
3425        {
3426            glNormal3fv(_array[_indices[index]].ptr());
3427        }
3428
3429        osg::Vec3*      _array;
3430        unsigned short* _indices;
3431    };
3432
3433    //////////////////////////////
3434
3435    struct C4
3436    {
3437        C4():_array(0) {}
3438
3439        bool valid() const { return _array!=0; }
3440
3441        void set(osg::Geometry* geometry)
3442        {
3443            _array = 0;
3444            osg::Array* array = geometry->getColorArray();
3445            if (array && array->getType()==osg::Array::Vec4ArrayType)
3446            {
3447                osg::Vec4Array* vec4array = static_cast<osg::Vec4Array*>(array);
3448                if (!vec4array->empty()) _array = &(vec4array->front());
3449            }
3450        }
3451
3452        inline void draw(unsigned int index) const
3453        {
3454            glVertex3fv(_array[index].ptr());
3455        }
3456
3457        osg::Vec4* _array;
3458    };
3459
3460    struct C4USI
3461    {
3462        C4USI():_array(0),_indices(0) {}
3463
3464        bool valid() const { return _array!=0 && _indices!=0; }
3465
3466        void set(osg::Geometry* geometry)
3467        {
3468            _array = 0;
3469            osg::Array* array = geometry->getColorArray();
3470            if (array && array->getType()==osg::Array::Vec4ArrayType)
3471            {
3472                osg::Vec4Array* vec4array = static_cast<osg::Vec4Array*>(array);
3473                if (!vec4array->empty()) _array = &(vec4array->front());
3474            }
3475
3476            _indices = 0;
3477            osg::IndexArray* indices = geometry->getColorIndices();
3478            if (indices && indices->getType()==osg::Array::UShortArrayType)
3479            {
3480                osg::UShortArray* ushortarray = static_cast<osg::UShortArray*>(array);
3481                if (!ushortarray->empty()) _indices = &(ushortarray->front());
3482            }
3483        }
3484
3485        inline void draw(unsigned int index) const
3486        {
3487            glColor4fv(_array[_indices[index]].ptr());
3488        }
3489
3490        osg::Vec4*      _array;
3491        unsigned short* _indices;
3492    };
3493
3494    //////////////////////////////
3495
3496    struct T2
3497    {
3498        T2():_array(0) {}
3499
3500        bool valid() const { return _array!=0; }
3501
3502        void set(osg::Geometry* geometry)
3503        {
3504            _array = 0;
3505            osg::Array* array = geometry->getTexCoordArray(0);
3506            if (array && array->getType()==osg::Array::Vec2ArrayType)
3507            {
3508                osg::Vec2Array* vec2array = static_cast<osg::Vec2Array*>(array);
3509                if (!vec2array->empty()) _array = &(vec2array->front());
3510            }
3511        }
3512
3513        inline void draw(unsigned int index) const
3514        {
3515            glTexCoord2fv(_array[index].ptr());
3516        }
3517
3518        osg::Vec2* _array;
3519    };
3520
3521    struct T2USI
3522    {
3523        T2USI():_array(0),_indices(0) {}
3524
3525        bool valid() const { return _array!=0 && _indices!=0; }
3526
3527        void set(osg::Geometry* geometry)
3528        {
3529            _array = 0;
3530            osg::Array* array = geometry->getTexCoordArray(0);
3531            if (array && array->getType()==osg::Array::Vec2ArrayType)
3532            {
3533                osg::Vec2Array* vec2array = static_cast<osg::Vec2Array*>(array);
3534                if (!vec2array->empty()) _array = &(vec2array->front());
3535            }
3536
3537            _indices = 0;
3538            osg::IndexArray* indices = geometry->getTexCoordIndices(0);
3539            if (indices && indices->getType()==osg::Array::UShortArrayType)
3540            {
3541                osg::UShortArray* ushortarray = static_cast<osg::UShortArray*>(array);
3542                if (!ushortarray->empty()) _indices = &(ushortarray->front());
3543            }
3544        }
3545
3546        inline void draw(unsigned int index) const
3547        {
3548            glTexCoord2fv(_array[_indices[index]].ptr());
3549        }
3550
3551        osg::Vec2*      _array;
3552        unsigned short* _indices;
3553    };
3554
3555
3556    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3557
3558    template < class T1 >
3559    struct DrawAttributeArrays_T : public DrawAttributeArrays
3560    {
3561        DrawAttributeArrays_T(osg::Geometry* geometry)
3562        {
3563
3564        }
3565
3566        virtual bool valid() const { return _t1.valid(); }
3567
3568        virtual void set(osg::Geometry* geometry)
3569        {
3570            _t1.set(geometry);
3571        }
3572
3573        virtual unsigned int draw(unsigned int index, unsigned int count) const
3574        {
3575            for(unsigned int i=0;i<count;++i,++index)
3576            {
3577                _t1.draw(index);
3578            }
3579            return index;
3580        }
3581
3582        T1 _t1;
3583    };
3584
3585    template < class T1, class T2 >
3586    struct DrawAttributeArrays_TT : public DrawAttributeArrays
3587    {
3588        DrawAttributeArrays_TT()
3589        {
3590        }
3591
3592        virtual bool valid() const { return _t1.valid() && _t2.valid(); }
3593
3594        virtual void set(osg::Geometry* geometry)
3595        {
3596            _t1.set(geometry);
3597            _t2.set(geometry);
3598        }
3599
3600        virtual unsigned int draw(unsigned int index, unsigned int count) const
3601        {
3602            for(unsigned int i=0;i<count;++i,++index)
3603            {
3604                _t1.draw(index);
3605                _t2.draw(index);
3606            }
3607            return index;
3608        }
3609
3610        T1 _t1;
3611        T1 _t2;
3612    };
3613
3614    template < class T1, class T2, class T3 >
3615    struct DrawAttributeArrays_TTT : public DrawAttributeArrays
3616    {
3617        DrawAttributeArrays_TTT()
3618        {
3619        }
3620
3621        virtual bool valid() const { return _t1.valid() && _t2.valid() && _t3.valid(); }
3622
3623        virtual void set(osg::Geometry* geometry)
3624        {
3625            _t1.set(geometry);
3626            _t2.set(geometry);
3627            _t3.set(geometry);
3628        }
3629
3630        virtual unsigned int draw(unsigned int index, unsigned int count) const
3631        {
3632            for(unsigned int i=0;i<count;++i,++index)
3633            {
3634                _t1.draw(index);
3635                _t2.draw(index);
3636                _t3.draw(index);
3637            }
3638            return index;
3639        }
3640
3641        T1 _t1;
3642        T2 _t2;
3643        T3 _t3;
3644    };
3645
3646    template < class T1, class T2, class T3, class T4 >
3647    struct DrawAttributeArrays_TTTT : public DrawAttributeArrays
3648    {
3649        DrawAttributeArrays_TTTT()
3650        {
3651        }
3652
3653        virtual bool valid() const { return _t1.valid() && _t2.valid() && _t3.valid() && _t4.valid(); }
3654
3655        virtual void set(osg::Geometry* geometry)
3656        {
3657            _t1.set(geometry);
3658            _t2.set(geometry);
3659            _t3.set(geometry);
3660            _t4.set(geometry);
3661        }
3662
3663        virtual unsigned int draw(unsigned int index, unsigned int count) const
3664        {
3665            for(unsigned int i=0;i<count;++i,++index)
3666            {
3667                _t1.draw(index);
3668                _t2.draw(index);
3669                _t3.draw(index);
3670                _t4.draw(index);
3671            }
3672            return index;
3673        }
3674
3675        T1 _t1;
3676        T2 _t2;
3677        T3 _t3;
3678        T4 _t4;
3679    };
3680
3681    template < class T1, class T2 >
3682    struct DrawAttributeArrays_TT_USI : public DrawAttributeArrays
3683    {
3684        DrawAttributeArrays_TT_USI()
3685        {
3686        }
3687
3688        virtual bool valid() const { return _t1.valid() && _t2.valid() && _indices!=0; }
3689
3690        virtual void set(osg::Geometry* geometry)
3691        {
3692            _t1.set(geometry);
3693            _t2.set(geometry);
3694
3695            _indices = 0;
3696            osg::IndexArray* indices = geometry->getVertexIndices();
3697            if (indices && indices->getType()==osg::Array::UShortArrayType)
3698            {
3699                osg::UShortArray* ushort3array = static_cast<osg::UShortArray*>(array);
3700                if (!ushort3array->empty()) _indices = &(ushort3array->front());
3701            }
3702        }
3703
3704        virtual unsigned int draw(unsigned int index, unsigned int count) const
3705        {
3706            for(unsigned int i=0;i<count;++i,++index)
3707            {
3708                unsigned int ivalue = _indices[index];
3709                _t1.draw(ivalue);
3710                _t2.draw(ivalue);
3711            }
3712            return index;
3713        }
3714
3715        T1 _t1;
3716        T2 _t2;
3717    };
3718
3719    template < class T1, class T2, class T3 >
3720    struct DrawAttributeArrays_TTT_USI : public DrawAttributeArrays
3721    {
3722        DrawAttributeArrays_TTT_USI()
3723        {
3724        }
3725
3726        virtual bool valid() const { return _t1.valid() && _t2.valid() && _t3.valid() && _indices!=0; }
3727
3728        virtual void set(osg::Geometry* geometry)
3729        {
3730            _t1.set(geometry);
3731            _t2.set(geometry);
3732            _t3.set(geometry);
3733
3734            _indices = 0;
3735            osg::IndexArray* indices = geometry->getVertexIndices();
3736            if (indices && indices->getType()==osg::Array::UShortArrayType)
3737            {
3738                osg::UShortArray* ushort3array = static_cast<osg::UShortArray*>(array);
3739                if (!ushort3array->empty()) _indices = &(ushort3array->front());
3740            }
3741        }
3742
3743        virtual unsigned int draw(unsigned int index, unsigned int count) const
3744        {
3745            for(unsigned int i=0;i<count;++i,++index)
3746            {
3747                unsigned int ivalue = _indices[index];
3748                _t1.draw(ivalue);
3749                _t2.draw(ivalue);
3750                _t3.draw(ivalue);
3751            }
3752            return index;
3753        }
3754
3755        T1 _t1;
3756        T2 _t2;
3757        T3 _t3;
3758    };
3759
3760    template < class T1, class T2, class T3, class T4 >
3761    struct DrawAttributeArrays_TTTT_USI : public DrawAttributeArrays
3762    {
3763        DrawAttributeArrays_TTTT_USI()
3764        {
3765        }
3766
3767        virtual bool valid() const { return _t1.valid() && _t2.valid() && _t3.valid() && _t4.valid() && _indices!=0; }
3768
3769        virtual void set(osg::Geometry* geometry)
3770        {
3771            _t1.set(geometry);
3772            _t2.set(geometry);
3773            _t3.set(geometry);
3774            _t4.set(geometry);
3775
3776            _indices = 0;
3777            osg::IndexArray* indices = geometry->getVertexIndices();
3778            if (indices && indices->getType()==osg::Array::UShortArrayType)
3779            {
3780                osg::UShortArray* ushort3array = static_cast<osg::UShortArray*>(array);
3781                if (!ushort3array->empty()) _indices = &(ushort3array->front());
3782            }
3783        }
3784
3785        virtual unsigned int draw(unsigned int index, unsigned int count) const
3786        {
3787            for(unsigned int i=0;i<count;++i,++index)
3788            {
3789                unsigned int ivalue = _indices[index];
3790                _t1.draw(ivalue);
3791                _t2.draw(ivalue);
3792                _t3.draw(ivalue);
3793                _t4.draw(ivalue);
3794            }
3795            return index;
3796        }
3797
3798        T1 _t1;
3799        T2 _t2;
3800        T3 _t3;
3801        T4 _t4;
3802    };
3803
3804    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3805
3806
3807    // One attribute x 2
3808
3809    typedef DrawAttributeArrays_T<V3>                    DrawAttributeArrays_V3;
3810    typedef DrawAttributeArrays_T<V3USI>                 DrawAttributeArrays_V3i;
3811
3812    // Two attributes x 15
3813
3814    typedef DrawAttributeArrays_TT<N3,V3>                DrawAttributeArrays_N3V3;
3815    typedef DrawAttributeArrays_TT<N3USI,V3>             DrawAttributeArrays_N3iV3;
3816    typedef DrawAttributeArrays_TT<N3,V3USI>             DrawAttributeArrays_N3V3i;
3817    typedef DrawAttributeArrays_TT<N3USI,V3USI>          DrawAttributeArrays_N3iV3i;
3818
3819    typedef DrawAttributeArrays_TT_USI<N3,V3>            DrawAttributeArrays_N3V3_i;
3820
3821    typedef DrawAttributeArrays_TT<C4,V3>                DrawAttributeArrays_C4V3;
3822    typedef DrawAttributeArrays_TT<C4USI,V3>             DrawAttributeArrays_C4iV3;
3823    typedef DrawAttributeArrays_TT<C4,V3USI>             DrawAttributeArrays_C4V3i;
3824    typedef DrawAttributeArrays_TT<C4USI,V3USI>          DrawAttributeArrays_C4iV3i;
3825
3826    typedef DrawAttributeArrays_TT_USI<C4,V3>            DrawAttributeArrays_C4V3_i;
3827
3828    typedef DrawAttributeArrays_TT<T2,V3>                DrawAttributeArrays_T2V3;
3829    typedef DrawAttributeArrays_TT<T2USI,V3>             DrawAttributeArrays_T2iV3;
3830    typedef DrawAttributeArrays_TT<T2,V3USI>             DrawAttributeArrays_T2V3i;
3831    typedef DrawAttributeArrays_TT<T2USI,V3USI>          DrawAttributeArrays_T2iV3i;
3832
3833    typedef DrawAttributeArrays_TT_USI<T2,V3>            DrawAttributeArrays_T2V3_i;
3834
3835    // Three attributes x 27
3836
3837    typedef DrawAttributeArrays_TTT<C4,N3,V3>            DrawAttributeArrays_C4N3V3;
3838    typedef DrawAttributeArrays_TTT<C4USI,N3,V3>         DrawAttributeArrays_C4iN3V3;
3839    typedef DrawAttributeArrays_TTT<C4,N3USI,V3>         DrawAttributeArrays_C4N3iV3;
3840    typedef DrawAttributeArrays_TTT<C4USI,N3USI,V3>      DrawAttributeArrays_C4iN3iV3;
3841
3842    typedef DrawAttributeArrays_TTT<C4,N3,V3USI>         DrawAttributeArrays_C4N3V3i;
3843    typedef DrawAttributeArrays_TTT<C4USI,N3,V3USI>      DrawAttributeArrays_C4iN3V3i;
3844    typedef DrawAttributeArrays_TTT<C4,N3USI,V3USI>      DrawAttributeArrays_C4N3iV3i;
3845    typedef DrawAttributeArrays_TTT<C4USI,N3USI,V3USI>   DrawAttributeArrays_C4iN3iV3i;
3846
3847    typedef DrawAttributeArrays_TTT_USI<C4,N3,V3>        DrawAttributeArrays_C4N3V3_i;
3848
3849
3850    typedef DrawAttributeArrays_TTT<T2,N3,V3>            DrawAttributeArrays_T2N3V3;
3851    typedef DrawAttributeArrays_TTT<T2USI,N3,V3>         DrawAttributeArrays_T2iN3V3;
3852    typedef DrawAttributeArrays_TTT<T2,N3USI,V3>         DrawAttributeArrays_T2iN3iV3;
3853    typedef DrawAttributeArrays_TTT<T2USI,N3USI,V3>      DrawAttributeArrays_T2N3iV3;
3854
3855    typedef DrawAttributeArrays_TTT<T2,N3,V3USI>         DrawAttributeArrays_T2N3V3i;
3856    typedef DrawAttributeArrays_TTT<T2USI,N3,V3USI>      DrawAttributeArrays_T2iN3V3i;
3857    typedef DrawAttributeArrays_TTT<T2,N3USI,V3USI>      DrawAttributeArrays_T2iN3iV3i;
3858    typedef DrawAttributeArrays_TTT<T2USI,N3USI,V3USI>   DrawAttributeArrays_T2N3iV3i;
3859
3860    typedef DrawAttributeArrays_TTT_USI<T2,N3,V3>        DrawAttributeArrays_T2N3V3_i;
3861
3862
3863
3864    typedef DrawAttributeArrays_TTT<T2,C4,V3>            DrawAttributeArrays_T2C4V3;
3865    typedef DrawAttributeArrays_TTT<T2USI,C4,V3>         DrawAttributeArrays_T2iC4V3;
3866    typedef DrawAttributeArrays_TTT<T2,C4USI,V3>         DrawAttributeArrays_T2C4iV3;
3867    typedef DrawAttributeArrays_TTT<T2USI,C4USI,V3>      DrawAttributeArrays_T2iC4iV3;
3868
3869    typedef DrawAttributeArrays_TTT<T2,C4,V3USI>         DrawAttributeArrays_T2C4V3i;
3870    typedef DrawAttributeArrays_TTT<T2USI,C4,V3USI>      DrawAttributeArrays_T2iC4V3i;
3871    typedef DrawAttributeArrays_TTT<T2,C4USI,V3USI>      DrawAttributeArrays_T2C4iV3i;
3872    typedef DrawAttributeArrays_TTT<T2USI,C4USI,V3USI>   DrawAttributeArrays_T2iC4iV3i;
3873
3874    typedef DrawAttributeArrays_TTT_USI<T2,C4,V3>        DrawAttributeArrays_T2C4V3_t;
3875
3876
3877    // Four attributes x 17
3878
3879    typedef DrawAttributeArrays_TTTT<T2,C4,N3,V3>                DrawAttributeArrays_T2C4N3V3;
3880    typedef DrawAttributeArrays_TTTT<T2USI,C4,N3,V3>             DrawAttributeArrays_T2iC4N3V3;
3881    typedef DrawAttributeArrays_TTTT<T2,C4USI,N3,V3>             DrawAttributeArrays_T2C4iN3V3;
3882    typedef DrawAttributeArrays_TTTT<T2USI,C4USI,N3,V3>          DrawAttributeArrays_T2iC4iN3V3;
3883
3884    typedef DrawAttributeArrays_TTTT<T2,C4,N3USI,V3>             DrawAttributeArrays_T2C4N3iV3;
3885    typedef DrawAttributeArrays_TTTT<T2USI,C4,N3USI,V3>          DrawAttributeArrays_T2iC4N3iV3;
3886    typedef DrawAttributeArrays_TTTT<T2,C4USI,N3USI,V3>           DrawAttributeArrays_T2C4iN3iV3;
3887    typedef DrawAttributeArrays_TTTT<T2USI,C4USI,N3USI,V3>       DrawAttributeArrays_T2iC4iN3iV3;
3888
3889    typedef DrawAttributeArrays_TTTT<T2,C4,N3,V3USI>             DrawAttributeArrays_T2C4N3V3i;
3890    typedef DrawAttributeArrays_TTTT<T2USI,C4,N3,V3USI>          DrawAttributeArrays_T2iC4N3V3i;
3891    typedef DrawAttributeArrays_TTTT<T2,C4USI,N3,V3USI>          DrawAttributeArrays_T2C4iN3V3i;
3892    typedef DrawAttributeArrays_TTTT<T2USI,C4USI,N3,V3USI>       DrawAttributeArrays_T2iC4iN3V3i;
3893
3894    typedef DrawAttributeArrays_TTTT<T2,C4,N3USI,V3USI>          DrawAttributeArrays_T2C4N3iV3i;
3895    typedef DrawAttributeArrays_TTTT<T2USI,C4,N3USI,V3USI>       DrawAttributeArrays_T2iC4N3iV3i;
3896    typedef DrawAttributeArrays_TTTT<T2,C4USI,N3USI,V3USI>       DrawAttributeArrays_T2C4iN3iV3i;
3897    typedef DrawAttributeArrays_TTTT<T2USI,C4USI,N3USI,V3USI>    DrawAttributeArrays_T2iC4iN3iV3i;
3898
3899    typedef DrawAttributeArrays_TTTT_USI<T2,C4,N3,V3>            DrawAttributeArrays_T2C4N3V3_i;
3900
3901    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3902
3903
3904#endif
Note: See TracBrowser for help on using the browser.