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

Revision 13497, 62.5 kB (checked in by robert, 12 hours ago)

Removed GL header as it's already included via the ${OPENSCENEGRAPH_OPENGL_HEADER} entry.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13#include <stdlib.h>
14
15#include <osg/Geometry>
16#include <osg/ArrayDispatchers>
17#include <osg/Notify>
18
19using namespace osg;
20
21
22Geometry::Geometry():
23    _containsDeprecatedData(false)
24{
25    _supportsVertexBufferObjects = true;
26    // temporary test
27    // setSupportsDisplayList(false);
28}
29
30Geometry::Geometry(const Geometry& geometry,const CopyOp& copyop):
31    Drawable(geometry,copyop),
32    _vertexArray(copyop(geometry._vertexArray.get())),
33    _normalArray(copyop(geometry._normalArray.get())),
34    _colorArray(copyop(geometry._colorArray.get())),
35    _secondaryColorArray(copyop(geometry._secondaryColorArray.get())),
36    _fogCoordArray(copyop(geometry._fogCoordArray.get())),
37    _containsDeprecatedData(geometry._containsDeprecatedData)
38{
39    _supportsVertexBufferObjects = true;
40    // temporary test
41    // setSupportsDisplayList(false);
42
43    for(PrimitiveSetList::const_iterator pitr=geometry._primitives.begin();
44        pitr!=geometry._primitives.end();
45        ++pitr)
46    {
47        PrimitiveSet* primitive = copyop(pitr->get());
48        if (primitive) _primitives.push_back(primitive);
49    }
50
51    for(ArrayList::const_iterator titr=geometry._texCoordList.begin();
52        titr!=geometry._texCoordList.end();
53        ++titr)
54    {
55        _texCoordList.push_back(copyop(titr->get()));
56    }
57
58    for(ArrayList::const_iterator vitr=geometry._vertexAttribList.begin();
59        vitr!=geometry._vertexAttribList.end();
60        ++vitr)
61    {
62        _vertexAttribList.push_back(copyop(vitr->get()));
63    }
64
65    if ((copyop.getCopyFlags() & osg::CopyOp::DEEP_COPY_ARRAYS))
66    {
67        if (_useVertexBufferObjects)
68        {
69            // copying of arrays doesn't set up buffer objects so we'll need to force
70            // Geometry to assign these, we'll do this by switching off VBO's then renabling them.
71            setUseVertexBufferObjects(false);
72            setUseVertexBufferObjects(true);
73        }
74    }
75
76}
77
78Geometry::~Geometry()
79{
80    // do dirty here to keep the getGLObjectSizeHint() estimate on the ball
81    dirtyDisplayList();
82
83    // no need to delete, all automatically handled by ref_ptr :-)
84}
85
86#define ARRAY_NOT_EMPTY(array) (array!=0 && array->getNumElements()!=0)
87
88bool Geometry::empty() const
89{
90    if (!_primitives.empty()) return false;
91    if (ARRAY_NOT_EMPTY(_vertexArray.get())) return false;
92    if (ARRAY_NOT_EMPTY(_normalArray.get())) return false;
93    if (ARRAY_NOT_EMPTY(_colorArray.get())) return false;
94    if (ARRAY_NOT_EMPTY(_secondaryColorArray.get())) return false;
95    if (ARRAY_NOT_EMPTY(_fogCoordArray.get())) return false;
96    if (!_texCoordList.empty()) return false;
97    if (!_vertexAttribList.empty()) return false;
98    return true;
99}
100
101void Geometry::setVertexArray(Array* array)
102{
103    _vertexArray = array;
104
105    dirtyDisplayList();
106    dirtyBound();
107
108    if (_useVertexBufferObjects && array) addVertexBufferObjectIfRequired(array);
109}
110
111void Geometry::setNormalArray(Array* array)
112{
113    _normalArray = array;
114
115    dirtyDisplayList();
116
117    if (_useVertexBufferObjects && array) addVertexBufferObjectIfRequired(array);
118}
119
120void Geometry::setColorArray(Array* array)
121{
122    _colorArray = array;
123
124    dirtyDisplayList();
125
126    if (_useVertexBufferObjects && array) addVertexBufferObjectIfRequired(array);
127}
128
129void Geometry::setSecondaryColorArray(Array* array)
130{
131    _secondaryColorArray = array;
132
133    dirtyDisplayList();
134
135    if (_useVertexBufferObjects && array) addVertexBufferObjectIfRequired(array);
136}
137
138void Geometry::setFogCoordArray(Array* array)
139{
140    _fogCoordArray = array;
141
142    dirtyDisplayList();
143
144    if (_useVertexBufferObjects && array) addVertexBufferObjectIfRequired(array);
145}
146
147#define SET_BINDING(array, ab)\
148    if (!array) \
149    { \
150        if (ab==BIND_OFF) return; \
151        OSG_NOTICE<<"Warning, can't assign attribute binding as no has been array assigned to set binding for."<<std::endl; \
152        return; \
153    } \
154    if (array->getBinding() == static_cast<osg::Array::Binding>(ab)) return; \
155    array->setBinding(static_cast<osg::Array::Binding>(ab));\
156    if (ab==BIND_PER_PRIMITIVE) _containsDeprecatedData = true;
157       
158
159#define GET_BINDING(array) (array!=0 ? static_cast<AttributeBinding>(array->getBinding()) : BIND_OFF)
160
161
162
163
164void Geometry::setTexCoordArray(unsigned int index,Array* array)
165{
166    if (_texCoordList.size()<=index)
167        _texCoordList.resize(index+1);
168
169    _texCoordList[index] = array;
170
171    // do we set to array BIND_PER_VERTEX?
172
173    dirtyDisplayList();
174
175    if (_useVertexBufferObjects && array)
176    {
177        addVertexBufferObjectIfRequired(array);
178    }
179}
180
181Array* Geometry::getTexCoordArray(unsigned int index)
182{
183    if (index<_texCoordList.size()) return _texCoordList[index].get();
184    else return 0;
185}
186
187const Array* Geometry::getTexCoordArray(unsigned int index) const
188{
189    if (index<_texCoordList.size()) return _texCoordList[index].get();
190    else return 0;
191}
192
193
194void Geometry::setVertexAttribArray(unsigned int index, Array* array)
195{
196    if (_vertexAttribList.size()<=index)
197        _vertexAttribList.resize(index+1);
198
199    _vertexAttribList[index] = array;
200
201    dirtyDisplayList();
202
203    if (_useVertexBufferObjects && array) addVertexBufferObjectIfRequired(array);
204}
205
206Array *Geometry::getVertexAttribArray(unsigned int index)
207{
208    if (index<_vertexAttribList.size()) return _vertexAttribList[index].get();
209    else return 0;
210}
211
212const Array *Geometry::getVertexAttribArray(unsigned int index) const
213{
214    if (index<_vertexAttribList.size()) return _vertexAttribList[index].get();
215    else return 0;
216}
217
218
219bool Geometry::addPrimitiveSet(PrimitiveSet* primitiveset)
220{
221    if (primitiveset)
222    {
223        if (_useVertexBufferObjects) addElementBufferObjectIfRequired(primitiveset);
224
225        _primitives.push_back(primitiveset);
226        dirtyDisplayList();
227        dirtyBound();
228        return true;
229    }
230    OSG_WARN<<"Warning: invalid index i or primitiveset passed to osg::Geometry::addPrimitiveSet(i,primitiveset), ignoring call."<<std::endl;
231    return false;
232}
233
234bool Geometry::setPrimitiveSet(unsigned int i,PrimitiveSet* primitiveset)
235{
236    if (i<_primitives.size() && primitiveset)
237    {
238        if (_useVertexBufferObjects) addElementBufferObjectIfRequired(primitiveset);
239
240        _primitives[i] = primitiveset;
241        dirtyDisplayList();
242        dirtyBound();
243        return true;
244    }
245    OSG_WARN<<"Warning: invalid index i or primitiveset passed to osg::Geometry::setPrimitiveSet(i,primitiveset), ignoring call."<<std::endl;
246    return false;
247}
248
249bool Geometry::insertPrimitiveSet(unsigned int i,PrimitiveSet* primitiveset)
250{
251
252    if (primitiveset)
253    {
254        if (_useVertexBufferObjects) addElementBufferObjectIfRequired(primitiveset);
255
256        if (i<_primitives.size())
257        {
258            _primitives.insert(_primitives.begin()+i,primitiveset);
259            dirtyDisplayList();
260            dirtyBound();
261            return true;
262        }
263        else if (i==_primitives.size())
264        {
265            return addPrimitiveSet(primitiveset);
266        }
267
268    }
269    OSG_WARN<<"Warning: invalid index i or primitiveset passed to osg::Geometry::insertPrimitiveSet(i,primitiveset), ignoring call."<<std::endl;
270    return false;
271}
272
273void Geometry::setPrimitiveSetList(const PrimitiveSetList& primitives)
274{
275    _primitives = primitives;
276    if (_useVertexBufferObjects)
277    {
278        for (unsigned int primitiveSetIndex=0;primitiveSetIndex<_primitives.size();++primitiveSetIndex)
279        {
280            addElementBufferObjectIfRequired(_primitives[primitiveSetIndex].get());
281        }
282
283    }
284    dirtyDisplayList(); dirtyBound();
285}
286
287bool Geometry::removePrimitiveSet(unsigned int i, unsigned int numElementsToRemove)
288{
289    if (numElementsToRemove==0) return false;
290
291    if (i<_primitives.size())
292    {
293        if (i+numElementsToRemove<=_primitives.size())
294        {
295            _primitives.erase(_primitives.begin()+i,_primitives.begin()+i+numElementsToRemove);
296        }
297        else
298        {
299            // asking to delete too many elements, report a warning, and delete to
300            // the end of the primitive list.
301            OSG_WARN<<"Warning: osg::Geometry::removePrimitiveSet(i,numElementsToRemove) has been asked to remove more elements than are available,"<<std::endl;
302            OSG_WARN<<"         removing on from i to the end of the list of primitive sets."<<std::endl;
303            _primitives.erase(_primitives.begin()+i,_primitives.end());
304        }
305
306        dirtyDisplayList();
307        dirtyBound();
308        return true;
309    }
310    OSG_WARN<<"Warning: invalid index i passed to osg::Geometry::removePrimitiveSet(i,numElementsToRemove), ignoring call."<<std::endl;
311    return false;
312}
313
314unsigned int Geometry::getPrimitiveSetIndex(const PrimitiveSet* primitiveset) const
315{
316    for (unsigned int primitiveSetIndex=0;primitiveSetIndex<_primitives.size();++primitiveSetIndex)
317    {
318        if (_primitives[primitiveSetIndex]==primitiveset) return primitiveSetIndex;
319    }
320    return _primitives.size(); // node not found.
321}
322
323unsigned int Geometry::getGLObjectSizeHint() const
324{
325    unsigned int totalSize = 0;
326    if (_vertexArray.valid()) totalSize += _vertexArray->getTotalDataSize();
327
328    if (_normalArray.valid()) totalSize += _normalArray->getTotalDataSize();
329
330    if (_colorArray.valid()) totalSize += _colorArray->getTotalDataSize();
331
332    if (_secondaryColorArray.valid()) totalSize += _secondaryColorArray->getTotalDataSize();
333
334    if (_fogCoordArray.valid()) totalSize += _fogCoordArray->getTotalDataSize();
335
336
337    unsigned int unit;
338    for(unit=0;unit<_texCoordList.size();++unit)
339    {
340        const Array* array = _texCoordList[unit].get();
341        if (array) totalSize += array->getTotalDataSize();
342
343    }
344
345    bool handleVertexAttributes = true;
346    if (handleVertexAttributes)
347    {
348        unsigned int index;
349        for( index = 0; index < _vertexAttribList.size(); ++index )
350        {
351            const Array* array = _vertexAttribList[index].get();
352            if (array) totalSize += array->getTotalDataSize();
353        }
354    }
355
356    for(PrimitiveSetList::const_iterator itr=_primitives.begin();
357        itr!=_primitives.end();
358        ++itr)
359    {
360
361        totalSize += 4*(*itr)->getNumIndices();
362
363    }
364
365
366    // do a very simply mapping of display list size proportional to vertex datasize.
367    return totalSize;
368}
369
370bool Geometry::getArrayList(ArrayList& arrayList) const
371{
372    unsigned int startSize = arrayList.size();
373
374    if (_vertexArray.valid()) arrayList.push_back(_vertexArray.get());
375    if (_normalArray.valid()) arrayList.push_back(_normalArray.get());
376    if (_colorArray.valid()) arrayList.push_back(_colorArray.get());
377    if (_secondaryColorArray.valid()) arrayList.push_back(_secondaryColorArray.get());
378    if (_fogCoordArray.valid()) arrayList.push_back(_fogCoordArray.get());
379
380    for(unsigned int unit=0;unit<_texCoordList.size();++unit)
381    {
382        Array* array = _texCoordList[unit].get();
383        if (array) arrayList.push_back(array);
384    }
385
386    for(unsigned int  index = 0; index < _vertexAttribList.size(); ++index )
387    {
388        Array* array = _vertexAttribList[index].get();
389        if (array) arrayList.push_back(array);
390    }
391
392    return arrayList.size()!=startSize;
393}
394
395bool Geometry::getDrawElementsList(DrawElementsList& drawElementsList) const
396{
397    unsigned int startSize = drawElementsList.size();
398
399    for(PrimitiveSetList::const_iterator itr = _primitives.begin();
400        itr != _primitives.end();
401        ++itr)
402    {
403        osg::DrawElements* de = (*itr)->getDrawElements();
404        if (de) drawElementsList.push_back(de);
405    }
406
407    return drawElementsList.size()!=startSize;
408}
409
410void Geometry::addVertexBufferObjectIfRequired(osg::Array* array)
411{
412    if (_useVertexBufferObjects)
413    {
414        if (!array->getVertexBufferObject())
415        {
416            array->setVertexBufferObject(getOrCreateVertexBufferObject());
417        }
418    }
419}
420
421void Geometry::addElementBufferObjectIfRequired(osg::PrimitiveSet* primitiveSet)
422{
423    if (_useVertexBufferObjects)
424    {
425        osg::DrawElements* drawElements = primitiveSet->getDrawElements();
426        if (drawElements && !drawElements->getElementBufferObject())
427        {
428            drawElements->setElementBufferObject(getOrCreateElementBufferObject());
429        }
430    }
431}
432
433osg::VertexBufferObject* Geometry::getOrCreateVertexBufferObject()
434{
435    ArrayList arrayList;
436    getArrayList(arrayList);
437
438    ArrayList::iterator vitr;
439    for(vitr = arrayList.begin();
440        vitr != arrayList.end();
441        ++vitr)
442    {
443        osg::Array* array = vitr->get();
444        if (array->getVertexBufferObject()) return array->getVertexBufferObject();
445    }
446
447    return new osg::VertexBufferObject;
448}
449
450osg::ElementBufferObject* Geometry::getOrCreateElementBufferObject()
451{
452    DrawElementsList drawElementsList;
453    getDrawElementsList(drawElementsList);
454
455    DrawElementsList::iterator deitr;
456    for(deitr = drawElementsList.begin();
457        deitr != drawElementsList.end();
458        ++deitr)
459    {
460        osg::DrawElements* elements = *deitr;
461        if (elements->getElementBufferObject()) return elements->getElementBufferObject();
462    }
463
464    return new osg::ElementBufferObject;
465}
466
467void Geometry::setUseVertexBufferObjects(bool flag)
468{
469    // flag = true;
470
471    // OSG_NOTICE<<"Geometry::setUseVertexBufferObjects("<<flag<<")"<<std::endl;
472
473    if (_useVertexBufferObjects==flag) return;
474
475    Drawable::setUseVertexBufferObjects(flag);
476
477    ArrayList arrayList;
478    getArrayList(arrayList);
479
480    DrawElementsList drawElementsList;
481    getDrawElementsList(drawElementsList);
482
483    typedef std::vector<osg::VertexBufferObject*>  VertexBufferObjectList;
484    typedef std::vector<osg::ElementBufferObject*>  ElementBufferObjectList;
485
486    if (_useVertexBufferObjects)
487    {
488        if (!arrayList.empty())
489        {
490
491            VertexBufferObjectList vboList;
492
493            osg::ref_ptr<osg::VertexBufferObject> vbo;
494
495            ArrayList::iterator vitr;
496            for(vitr = arrayList.begin();
497                vitr != arrayList.end() && !vbo;
498                ++vitr)
499            {
500                osg::Array* array = vitr->get();
501                if (array->getVertexBufferObject()) vbo = array->getVertexBufferObject();
502            }
503
504            if (!vbo) vbo = new osg::VertexBufferObject;
505
506            for(vitr = arrayList.begin();
507                vitr != arrayList.end();
508                ++vitr)
509            {
510                osg::Array* array = vitr->get();
511                if (!array->getVertexBufferObject()) array->setVertexBufferObject(vbo.get());
512            }
513        }
514
515        if (!drawElementsList.empty())
516        {
517            ElementBufferObjectList eboList;
518
519            osg::ref_ptr<osg::ElementBufferObject> ebo;
520
521            DrawElementsList::iterator deitr;
522            for(deitr = drawElementsList.begin();
523                deitr != drawElementsList.end();
524                ++deitr)
525            {
526                osg::DrawElements* elements = *deitr;
527                if (elements->getElementBufferObject()) ebo = elements->getElementBufferObject();
528            }
529
530            if (!ebo) ebo = new osg::ElementBufferObject;
531
532            for(deitr = drawElementsList.begin();
533                deitr != drawElementsList.end();
534                ++deitr)
535            {
536                osg::DrawElements* elements = *deitr;
537                if (!elements->getElementBufferObject()) elements->setElementBufferObject(ebo.get());
538            }
539        }
540    }
541    else
542    {
543        for(ArrayList::iterator vitr = arrayList.begin();
544            vitr != arrayList.end();
545            ++vitr)
546        {
547            osg::Array* array = vitr->get();
548            if (array->getVertexBufferObject()) array->setVertexBufferObject(0);
549        }
550
551        for(DrawElementsList::iterator deitr = drawElementsList.begin();
552            deitr != drawElementsList.end();
553            ++deitr)
554        {
555            osg::DrawElements* elements = *deitr;
556            if (elements->getElementBufferObject()) elements->setElementBufferObject(0);
557        }
558    }
559}
560
561void Geometry::dirtyDisplayList()
562{
563    Drawable::dirtyDisplayList();
564}
565
566void Geometry::resizeGLObjectBuffers(unsigned int maxSize)
567{
568    Drawable::resizeGLObjectBuffers(maxSize);
569
570    ArrayList arrays;
571    if (getArrayList(arrays))
572    {
573        for(ArrayList::iterator itr = arrays.begin();
574            itr != arrays.end();
575            ++itr)
576        {
577            (*itr)->resizeGLObjectBuffers(maxSize);
578        }
579    }
580
581    DrawElementsList drawElements;
582    if (getDrawElementsList(drawElements))
583    {
584        for(DrawElementsList::iterator itr = drawElements.begin();
585            itr != drawElements.end();
586            ++itr)
587        {
588            (*itr)->resizeGLObjectBuffers(maxSize);
589        }
590    }
591}
592
593void Geometry::releaseGLObjects(State* state) const
594{
595    Drawable::releaseGLObjects(state);
596
597    ArrayList arrays;
598    if (getArrayList(arrays))
599    {
600        for(ArrayList::iterator itr = arrays.begin();
601            itr != arrays.end();
602            ++itr)
603        {
604            (*itr)->releaseGLObjects(state);
605        }
606    }
607
608    DrawElementsList drawElements;
609    if (getDrawElementsList(drawElements))
610    {
611        for(DrawElementsList::iterator itr = drawElements.begin();
612            itr != drawElements.end();
613            ++itr)
614        {
615            (*itr)->releaseGLObjects(state);
616        }
617    }
618
619}
620
621void Geometry::compileGLObjects(RenderInfo& renderInfo) const
622{
623    bool useVertexArrays = _supportsVertexBufferObjects &&
624                           _useVertexBufferObjects &&
625                           renderInfo.getState()->isVertexBufferObjectSupported();
626    if (useVertexArrays)
627    {
628        State& state = *renderInfo.getState();
629        unsigned int contextID = state.getContextID();
630        GLBufferObject::Extensions* extensions = GLBufferObject::getExtensions(contextID, true);
631        if (!extensions) return;
632
633        typedef std::set<BufferObject*> BufferObjects;
634        BufferObjects bufferObjects;
635
636        // first collect all the active unique BufferObjects
637        if (_vertexArray.valid() && _vertexArray->getBufferObject()) bufferObjects.insert(_vertexArray->getBufferObject());
638        if (_normalArray.valid() && _normalArray->getBufferObject()) bufferObjects.insert(_normalArray->getBufferObject());
639        if (_colorArray.valid() && _colorArray->getBufferObject()) bufferObjects.insert(_colorArray->getBufferObject());
640        if (_secondaryColorArray.valid() && _secondaryColorArray->getBufferObject()) bufferObjects.insert(_secondaryColorArray->getBufferObject());
641        if (_fogCoordArray.valid() && _fogCoordArray->getBufferObject()) bufferObjects.insert(_fogCoordArray->getBufferObject());
642
643        for(ArrayList::const_iterator itr = _texCoordList.begin();
644            itr != _texCoordList.end();
645            ++itr)
646        {
647            if (itr->valid() && (*itr)->getBufferObject()) bufferObjects.insert((*itr)->getBufferObject());
648        }
649
650        for(ArrayList::const_iterator itr = _vertexAttribList.begin();
651            itr != _vertexAttribList.end();
652            ++itr)
653        {
654            if (itr->valid() && (*itr)->getBufferObject()) bufferObjects.insert((*itr)->getBufferObject());
655        }
656
657        for(PrimitiveSetList::const_iterator itr = _primitives.begin();
658            itr != _primitives.end();
659            ++itr)
660        {
661            if ((*itr)->getBufferObject()) bufferObjects.insert((*itr)->getBufferObject());
662        }
663
664        //osg::ElapsedTime timer;
665
666        // now compile any buffer objects that require it.
667        for(BufferObjects::iterator itr = bufferObjects.begin();
668            itr != bufferObjects.end();
669            ++itr)
670        {
671            GLBufferObject* glBufferObject = (*itr)->getOrCreateGLBufferObject(contextID);
672            if (glBufferObject && glBufferObject->isDirty())
673            {
674                // OSG_NOTICE<<"Compile buffer "<<glBufferObject<<std::endl;
675                glBufferObject->compileBuffer();
676            }
677        }
678
679        // OSG_NOTICE<<"Time to compile "<<timer.elapsedTime_m()<<"ms"<<std::endl;
680
681        // unbind the BufferObjects
682        extensions->glBindBuffer(GL_ARRAY_BUFFER_ARB,0);
683        extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB,0);
684
685    }
686    else
687    {
688        Drawable::compileGLObjects(renderInfo);
689    }
690}
691
692void Geometry::drawImplementation(RenderInfo& renderInfo) const
693{
694    if (_containsDeprecatedData)
695    {
696        OSG_WARN<<"Geometry::drawImplementation() unable to render due to deprecated data, call geometry->fixDeprecatedData();"<<std::endl;
697        return;
698    }
699   
700    State& state = *renderInfo.getState();
701
702    bool checkForGLErrors = state.getCheckForGLErrors()==osg::State::ONCE_PER_ATTRIBUTE;
703    if (checkForGLErrors) state.checkGLErrors("start of Geometry::drawImplementation()");
704
705    bool usingVertexBufferObjects = _useVertexBufferObjects && state.isVertexBufferObjectSupported();
706    bool handleVertexAttributes = !_vertexAttribList.empty();
707
708    ArrayDispatchers& arrayDispatchers = state.getArrayDispatchers();
709
710    arrayDispatchers.reset();
711    arrayDispatchers.setUseVertexAttribAlias(state.getUseVertexAttributeAliasing());
712
713    arrayDispatchers.activateNormalArray(_normalArray.get());
714    arrayDispatchers.activateColorArray(_colorArray.get());
715    arrayDispatchers.activateSecondaryColorArray(_secondaryColorArray.get());
716    arrayDispatchers.activateFogCoordArray(_fogCoordArray.get());
717
718    if (handleVertexAttributes)
719    {
720        for(unsigned int unit=0;unit<_vertexAttribList.size();++unit)
721        {
722            arrayDispatchers.activateVertexAttribArray(unit, _vertexAttribList[unit].get());
723        }
724    }
725
726    // dispatch any attributes that are bound overall
727    arrayDispatchers.dispatch(BIND_OVERALL,0);
728
729    state.lazyDisablingOfVertexAttributes();
730
731    // set up arrays
732    if( _vertexArray.valid() )
733        state.setVertexPointer(_vertexArray.get());
734
735    if (_normalArray.valid() && _normalArray->getBinding()==osg::Array::BIND_PER_VERTEX)
736        state.setNormalPointer(_normalArray.get());
737
738    if (_colorArray.valid() && _colorArray->getBinding()==osg::Array::BIND_PER_VERTEX)
739        state.setColorPointer(_colorArray.get());
740
741    if (_secondaryColorArray.valid() && _secondaryColorArray->getBinding()==osg::Array::BIND_PER_VERTEX)
742        state.setSecondaryColorPointer(_secondaryColorArray.get());
743
744    if (_fogCoordArray.valid() && _fogCoordArray->getBinding()==osg::Array::BIND_PER_VERTEX)
745        state.setFogCoordPointer(_fogCoordArray.get());
746
747    for(unsigned int unit=0;unit<_texCoordList.size();++unit)
748    {
749        const Array* array = _texCoordList[unit].get();
750        if (array)
751        {
752            state.setTexCoordPointer(unit,array);
753        }
754    }
755
756    if( handleVertexAttributes )
757    {
758        for(unsigned int index = 0; index < _vertexAttribList.size(); ++index )
759        {
760            const Array* array = _vertexAttribList[index].get();
761            if(array && array->getBinding()==osg::Array::BIND_PER_VERTEX)
762            {
763                state.setVertexAttribPointer( index, array, _vertexAttribList[index]->getNormalize() );
764            }
765        }
766    }
767
768    state.applyDisablingOfVertexAttributes();
769
770    bool bindPerPrimitiveSetActive = arrayDispatchers.active(BIND_PER_PRIMITIVE_SET);
771
772    if (checkForGLErrors) state.checkGLErrors("Geometry::drawImplementation() after vertex arrays setup.");
773
774    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
775    //
776    // draw the primitives themselves.
777    //
778    for(unsigned int primitiveSetNum=0; primitiveSetNum!=_primitives.size(); ++primitiveSetNum)
779    {
780        // dispatch any attributes that are bound per primitive
781        if (bindPerPrimitiveSetActive) arrayDispatchers.dispatch(BIND_PER_PRIMITIVE_SET, primitiveSetNum);
782
783        const PrimitiveSet* primitiveset = _primitives[primitiveSetNum].get();
784
785        primitiveset->draw(state, usingVertexBufferObjects);
786    }
787
788    // unbind the VBO's if any are used.
789    state.unbindVertexBufferObject();
790    state.unbindElementBufferObject();
791
792    if (checkForGLErrors) state.checkGLErrors("end of Geometry::drawImplementation().");
793}
794
795class AttributeFunctorArrayVisitor : public ArrayVisitor
796{
797    public:
798
799        AttributeFunctorArrayVisitor(Drawable::AttributeFunctor& af):
800            _af(af),
801            _type(0) {}
802
803        virtual ~AttributeFunctorArrayVisitor() {}
804
805        virtual void apply(ByteArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
806        virtual void apply(ShortArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
807        virtual void apply(IntArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
808        virtual void apply(UByteArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
809        virtual void apply(UShortArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
810        virtual void apply(UIntArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
811        virtual void apply(Vec4ubArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
812        virtual void apply(FloatArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
813        virtual void apply(Vec2Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
814        virtual void apply(Vec3Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
815        virtual void apply(Vec4Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
816        virtual void apply(DoubleArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
817        virtual void apply(Vec2dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
818        virtual void apply(Vec3dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
819        virtual void apply(Vec4dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
820
821
822        inline void applyArray(Drawable::AttributeType type,Array* array)
823        {
824            if (array)
825            {
826                _type = type;
827                array->accept(*this);
828            }
829        }
830
831    protected:
832
833        AttributeFunctorArrayVisitor& operator = (const AttributeFunctorArrayVisitor&) { return *this; }
834        Drawable::AttributeFunctor&   _af;
835        Drawable::AttributeType       _type;
836};
837
838void Geometry::accept(AttributeFunctor& af)
839{
840    AttributeFunctorArrayVisitor afav(af);
841
842    if (_vertexArray.valid())
843    {
844        afav.applyArray(VERTICES,_vertexArray.get());
845    }
846    else if (_vertexAttribList.size()>0)
847    {
848        OSG_INFO<<"Geometry::accept(AttributeFunctor& af): Using vertex attribute instead"<<std::endl;
849        afav.applyArray(VERTICES,_vertexAttribList[0].get());
850    }
851
852    afav.applyArray(NORMALS,_normalArray.get());
853    afav.applyArray(COLORS,_colorArray.get());
854    afav.applyArray(SECONDARY_COLORS,_secondaryColorArray.get());
855    afav.applyArray(FOG_COORDS,_fogCoordArray.get());
856
857    for(unsigned unit=0;unit<_texCoordList.size();++unit)
858    {
859        afav.applyArray((AttributeType)(TEXTURE_COORDS_0+unit),_texCoordList[unit].get());
860    }
861
862    for(unsigned int index=0; index<_vertexAttribList.size(); ++index)
863    {
864        afav.applyArray(index,_vertexAttribList[index].get());
865    }
866}
867
868class ConstAttributeFunctorArrayVisitor : public ConstArrayVisitor
869{
870    public:
871
872        ConstAttributeFunctorArrayVisitor(Drawable::ConstAttributeFunctor& af):
873            _af(af),
874            _type(0) {}
875
876        virtual ~ConstAttributeFunctorArrayVisitor() {}
877
878        virtual void apply(const ByteArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
879        virtual void apply(const ShortArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
880        virtual void apply(const IntArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
881        virtual void apply(const UByteArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
882        virtual void apply(const UShortArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
883        virtual void apply(const UIntArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
884        virtual void apply(const Vec4ubArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
885        virtual void apply(const FloatArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
886        virtual void apply(const Vec2Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
887        virtual void apply(const Vec3Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
888        virtual void apply(const Vec4Array& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
889        virtual void apply(const DoubleArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
890        virtual void apply(const Vec2dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
891        virtual void apply(const Vec3dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
892        virtual void apply(const Vec4dArray& array) {  if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
893
894
895        inline void applyArray(Drawable::AttributeType type,const Array* array)
896        {
897            if (array)
898            {
899                _type = type;
900                array->accept(*this);
901            }
902        }
903
904protected:
905
906        ConstAttributeFunctorArrayVisitor& operator = (const ConstAttributeFunctorArrayVisitor&) { return *this; }
907
908        Drawable::ConstAttributeFunctor&    _af;
909        Drawable::AttributeType             _type;
910};
911
912void Geometry::accept(ConstAttributeFunctor& af) const
913{
914    ConstAttributeFunctorArrayVisitor afav(af);
915
916    if (_vertexArray.valid())
917    {
918        afav.applyArray(VERTICES,_vertexArray.get());
919    }
920    else if (_vertexAttribList.size()>0)
921    {
922        OSG_INFO<<"Geometry::accept(ConstAttributeFunctor& af): Using vertex attribute instead"<<std::endl;
923        afav.applyArray(VERTICES,_vertexAttribList[0].get());
924    }
925
926    afav.applyArray(NORMALS,_normalArray.get());
927    afav.applyArray(COLORS,_colorArray.get());
928    afav.applyArray(SECONDARY_COLORS,_secondaryColorArray.get());
929    afav.applyArray(FOG_COORDS,_fogCoordArray.get());
930
931    for(unsigned unit=0;unit<_texCoordList.size();++unit)
932    {
933        afav.applyArray((AttributeType)(TEXTURE_COORDS_0+unit),_texCoordList[unit].get());
934    }
935
936    for(unsigned int index=0; index<_vertexAttribList.size(); ++index)
937    {
938        afav.applyArray(index,_vertexAttribList[index].get());
939    }
940}
941
942void Geometry::accept(PrimitiveFunctor& functor) const
943{
944    const osg::Array* vertices = _vertexArray.get();
945
946    if (!vertices && _vertexAttribList.size()>0)
947    {
948        OSG_INFO<<"Using vertex attribute instead"<<std::endl;
949        vertices = _vertexAttribList[0].get();
950    }
951
952    if (!vertices || vertices->getNumElements()==0) return;
953
954    if (_containsDeprecatedData && dynamic_cast<const osg::IndexArray*>(vertices->getUserData())!=0)
955    {
956        OSG_WARN<<"Geometry::accept(PrimitiveFunctor& functor) unable to work due to deprecated data, call geometry->fixDeprecatedData();"<<std::endl;
957        return;
958    }
959
960    switch(vertices->getType())
961    {
962    case(Array::Vec2ArrayType):
963        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec2*>(vertices->getDataPointer()));
964        break;
965    case(Array::Vec3ArrayType):
966        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec3*>(vertices->getDataPointer()));
967        break;
968    case(Array::Vec4ArrayType):
969        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec4*>(vertices->getDataPointer()));
970        break;
971    case(Array::Vec2dArrayType):
972        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec2d*>(vertices->getDataPointer()));
973        break;
974    case(Array::Vec3dArrayType):
975        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec3d*>(vertices->getDataPointer()));
976        break;
977    case(Array::Vec4dArrayType):
978        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec4d*>(vertices->getDataPointer()));
979        break;
980    default:
981        OSG_WARN<<"Warning: Geometry::accept(PrimitiveFunctor&) cannot handle Vertex Array type"<<vertices->getType()<<std::endl;
982        return;
983    }
984
985    for(PrimitiveSetList::const_iterator itr=_primitives.begin();
986        itr!=_primitives.end();
987        ++itr)
988    {
989        (*itr)->accept(functor);
990    }
991}
992
993void Geometry::accept(PrimitiveIndexFunctor& functor) const
994{
995    const osg::Array* vertices = _vertexArray.get();
996
997    if (!vertices && _vertexAttribList.size()>0)
998    {
999        OSG_INFO<<"Geometry::accept(PrimitiveIndexFunctor& functor): Using vertex attribute instead"<<std::endl;
1000        vertices = _vertexAttribList[0].get();
1001    }
1002
1003    if (!vertices || vertices->getNumElements()==0) return;
1004
1005    if (_containsDeprecatedData && dynamic_cast<const osg::IndexArray*>(vertices->getUserData())!=0)
1006    {
1007        OSG_WARN<<"Geometry::accept(PrimitiveIndexFunctor& functor) unable to work due to deprecated data, call geometry->fixDeprecatedData();"<<std::endl;
1008        return;
1009    }
1010
1011    switch(vertices->getType())
1012    {
1013    case(Array::Vec2ArrayType):
1014        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec2*>(vertices->getDataPointer()));
1015        break;
1016    case(Array::Vec3ArrayType):
1017        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec3*>(vertices->getDataPointer()));
1018        break;
1019    case(Array::Vec4ArrayType):
1020        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec4*>(vertices->getDataPointer()));
1021        break;
1022    case(Array::Vec2dArrayType):
1023        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec2d*>(vertices->getDataPointer()));
1024        break;
1025    case(Array::Vec3dArrayType):
1026        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec3d*>(vertices->getDataPointer()));
1027        break;
1028    case(Array::Vec4dArrayType):
1029        functor.setVertexArray(vertices->getNumElements(),static_cast<const Vec4d*>(vertices->getDataPointer()));
1030        break;
1031    default:
1032        OSG_WARN<<"Warning: Geometry::accept(PrimitiveIndexFunctor&) cannot handle Vertex Array type"<<vertices->getType()<<std::endl;
1033        return;
1034    }
1035
1036    for(PrimitiveSetList::const_iterator itr=_primitives.begin();
1037        itr!=_primitives.end();
1038        ++itr)
1039    {
1040        (*itr)->accept(functor);
1041    }
1042}
1043
1044Geometry* osg::createTexturedQuadGeometry(const Vec3& corner,const Vec3& widthVec,const Vec3& heightVec, float l, float b, float r, float t)
1045{
1046    Geometry* geom = new Geometry;
1047
1048    Vec3Array* coords = new Vec3Array(4);
1049    (*coords)[0] = corner+heightVec;
1050    (*coords)[1] = corner;
1051    (*coords)[2] = corner+widthVec;
1052    (*coords)[3] = corner+widthVec+heightVec;
1053    geom->setVertexArray(coords);
1054
1055    Vec2Array* tcoords = new Vec2Array(4);
1056    (*tcoords)[0].set(l,t);
1057    (*tcoords)[1].set(l,b);
1058    (*tcoords)[2].set(r,b);
1059    (*tcoords)[3].set(r,t);
1060    geom->setTexCoordArray(0,tcoords);
1061
1062    osg::Vec4Array* colours = new osg::Vec4Array(1);
1063    (*colours)[0].set(1.0f,1.0f,1.0,1.0f);
1064    geom->setColorArray(colours);
1065    geom->setColorBinding(Geometry::BIND_OVERALL);
1066
1067    osg::Vec3Array* normals = new osg::Vec3Array(1);
1068    (*normals)[0] = widthVec^heightVec;
1069    (*normals)[0].normalize();
1070    geom->setNormalArray(normals);
1071    geom->setNormalBinding(Geometry::BIND_OVERALL);
1072
1073#if defined(OSG_GLES1_AVAILABLE) || !defined(OSG_GLES2_AVAILABLE)
1074    DrawElementsUByte* elems = new DrawElementsUByte(PrimitiveSet::TRIANGLES);
1075    elems->push_back(0);
1076    elems->push_back(1);
1077    elems->push_back(2);
1078   
1079    elems->push_back(2);
1080    elems->push_back(3);
1081    elems->push_back(0);
1082    geom->addPrimitiveSet(elems);
1083#else
1084    geom->addPrimitiveSet(new DrawArrays(PrimitiveSet::QUADS,0,4));
1085#endif
1086
1087    return geom;
1088}
1089
1090//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1091//
1092// Deprecated methods.
1093//
1094void Geometry::setNormalBinding(AttributeBinding ab)
1095{
1096    SET_BINDING(_normalArray.get(), ab)
1097
1098    dirtyDisplayList();
1099}
1100
1101Geometry::AttributeBinding Geometry::getNormalBinding() const
1102{
1103    return GET_BINDING(_normalArray.get());
1104}
1105       
1106void Geometry::setColorBinding(AttributeBinding ab)
1107{
1108    SET_BINDING(_colorArray.get(), ab)
1109
1110    dirtyDisplayList();
1111}
1112
1113Geometry::AttributeBinding Geometry::getColorBinding() const
1114{
1115    return GET_BINDING(_colorArray.get());
1116}
1117       
1118void Geometry::setSecondaryColorBinding(AttributeBinding ab)
1119{
1120    SET_BINDING(_secondaryColorArray.get(), ab)
1121
1122    dirtyDisplayList();
1123}
1124
1125Geometry::AttributeBinding Geometry::getSecondaryColorBinding() const
1126{
1127    return GET_BINDING(_secondaryColorArray.get());
1128}
1129       
1130void Geometry::setFogCoordBinding(AttributeBinding ab)
1131{
1132    SET_BINDING(_fogCoordArray.get(), ab)
1133
1134    dirtyDisplayList();
1135}
1136
1137Geometry::AttributeBinding Geometry::getFogCoordBinding() const
1138{
1139    return GET_BINDING(_fogCoordArray.get());
1140}
1141
1142void Geometry::setVertexAttribBinding(unsigned int index,AttributeBinding ab)
1143{
1144    if (index<_vertexAttribList.size() && _vertexAttribList[index].valid())
1145    {
1146        if (_vertexAttribList[index]->getBinding()==static_cast<osg::Array::Binding>(ab)) return;
1147
1148        _vertexAttribList[index]->setBinding(static_cast<osg::Array::Binding>(ab));
1149       
1150        dirtyDisplayList();
1151    }
1152    else
1153    {
1154        OSG_NOTICE<<"Warning, can't assign attribute binding as no has been array assigned to set binding for."<<std::endl;
1155    }
1156}
1157
1158Geometry::AttributeBinding Geometry::getVertexAttribBinding(unsigned int index) const
1159{
1160    if (index<_vertexAttribList.size() && _vertexAttribList[index].valid()) return static_cast<AttributeBinding>(_vertexAttribList[index]->getBinding());
1161    else return BIND_OFF;
1162}
1163
1164void Geometry::setVertexAttribNormalize(unsigned int index,GLboolean norm)
1165{
1166    if (index<_vertexAttribList.size() && _vertexAttribList[index].valid())
1167    {
1168        _vertexAttribList[index]->setNormalize(norm);
1169       
1170        dirtyDisplayList();
1171    }
1172}
1173
1174GLboolean Geometry::getVertexAttribNormalize(unsigned int index) const
1175{
1176    if (index<_vertexAttribList.size() && _vertexAttribList[index].valid()) return _vertexAttribList[index]->getNormalize();
1177    else return GL_FALSE;
1178}
1179
1180////////////////////////////////////////////////////////////////////////////////////////////////////////
1181//
1182//  Helper methods
1183//
1184bool Geometry::containsSharedArrays() const
1185{
1186    unsigned int numSharedArrays = 0;
1187
1188    if (getVertexArray() && getVertexArray()->referenceCount()>1) ++numSharedArrays;
1189    if (getNormalArray() && getNormalArray()->referenceCount()>1) ++numSharedArrays;
1190    if (getColorArray() && getColorArray()->referenceCount()>1) ++numSharedArrays;
1191    if (getSecondaryColorArray() && getSecondaryColorArray()->referenceCount()>1) ++numSharedArrays;
1192    if (getFogCoordArray() && getFogCoordArray()->referenceCount()>1) ++numSharedArrays;
1193
1194    for(unsigned int ti=0;ti<getNumTexCoordArrays();++ti)
1195    {
1196        if (getTexCoordArray(ti) && getTexCoordArray(ti)->referenceCount()>1) ++numSharedArrays;
1197    }
1198
1199    for(unsigned int vi=0;vi<_vertexAttribList.size();++vi)
1200    {
1201        if (getVertexAttribArray(vi) && getVertexAttribArray(vi)->referenceCount()>1) ++numSharedArrays;
1202    }
1203    return numSharedArrays!=0;
1204}
1205
1206void Geometry::duplicateSharedArrays()
1207{
1208    #define DUPLICATE_IF_REQUIRED(A) \
1209        if (get##A() && get##A()->referenceCount()>1) \
1210        { \
1211            set##A(osg::clone(get##A(), osg::CopyOp::DEEP_COPY_ARRAYS)); \
1212        }
1213
1214    DUPLICATE_IF_REQUIRED(VertexArray)
1215    DUPLICATE_IF_REQUIRED(NormalArray)
1216    DUPLICATE_IF_REQUIRED(ColorArray)
1217    DUPLICATE_IF_REQUIRED(SecondaryColorArray)
1218    DUPLICATE_IF_REQUIRED(FogCoordArray)
1219
1220    for(unsigned int ti=0;ti<getNumTexCoordArrays();++ti)
1221    {
1222        if (getTexCoordArray(ti) && getTexCoordArray(ti)->referenceCount()>1)
1223        {
1224            setTexCoordArray(ti, osg::clone(getTexCoordArray(ti),osg::CopyOp::DEEP_COPY_ARRAYS));
1225        }
1226    }
1227
1228    for(unsigned int vi=0;vi<_vertexAttribList.size();++vi)
1229    {
1230        if (getVertexAttribArray(vi) && getVertexAttribArray(vi)->referenceCount()>1)
1231        {
1232            setVertexAttribArray(vi, osg::clone(getVertexAttribArray(vi),osg::CopyOp::DEEP_COPY_ARRAYS));
1233        }
1234    }
1235}
1236
1237inline osg::IndexArray* getIndexArray(osg::Array* array)
1238{
1239    return array ? dynamic_cast<osg::IndexArray*>(array->getUserData()) : 0;
1240}
1241
1242inline bool containsDeprecatedUsage(osg::Array* array)
1243{
1244    if (array)
1245    {
1246        if (array->getBinding()==3 /* BIND_PER_PRIMITIVE */) return true;
1247        if (dynamic_cast<osg::IndexArray*>(array->getUserData())!=0) return true;
1248    }
1249    return true;
1250}
1251
1252bool Geometry::checkForDeprecatedData()
1253{
1254    _containsDeprecatedData = false;
1255   
1256    if (containsDeprecatedUsage(_vertexArray.get())) _containsDeprecatedData = true;
1257
1258    if (containsDeprecatedUsage(_normalArray.get())) _containsDeprecatedData = true;
1259
1260    if (containsDeprecatedUsage(_colorArray.get())) _containsDeprecatedData = true;
1261
1262    if (containsDeprecatedUsage(_secondaryColorArray.get())) _containsDeprecatedData = true;
1263
1264    if (containsDeprecatedUsage(_fogCoordArray.get())) _containsDeprecatedData = true;
1265
1266    for(unsigned int ti=0;ti<getNumTexCoordArrays();++ti)
1267    {
1268        if (containsDeprecatedUsage(_texCoordList[ti].get())) _containsDeprecatedData = true;
1269    }
1270
1271    for(unsigned int vi=0;vi<getNumVertexAttribArrays();++vi)
1272    {
1273        if (containsDeprecatedUsage(_vertexAttribList[vi].get())) _containsDeprecatedData = true;
1274    }
1275
1276    return _containsDeprecatedData;
1277}
1278
1279static osg::Array* expandIndexArray(const osg::Array* sourceArray, const osg::IndexArray* indices)
1280{
1281    osg::ref_ptr<Array> targetArray = osg::cloneType(sourceArray);
1282    targetArray->setBinding(sourceArray->getBinding());
1283    targetArray->setNormalize(sourceArray->getNormalize());
1284    targetArray->setPreserveDataType(sourceArray->getPreserveDataType());
1285    targetArray->resizeArray(indices->getNumElements());
1286   
1287    unsigned int elementSize = sourceArray->getElementSize();
1288    const char* sourcePtr = static_cast<const char*>(sourceArray->getDataPointer());
1289    char* targetPtr = const_cast<char*>(static_cast<const char*>(targetArray->getDataPointer()));
1290    for(unsigned int i=0; i<indices->getNumElements(); ++i)
1291    {
1292        unsigned int vi = indices->index(i);
1293        const char* sourceElementPtr = sourcePtr + elementSize*vi;
1294        char* targetElementPtr = targetPtr + elementSize*i;
1295        for(unsigned int j=0; j<elementSize; ++j)
1296        {
1297            *targetElementPtr++ = *sourceElementPtr++;
1298        }
1299    }
1300    return targetArray.release();
1301}
1302
1303typedef std::pair< osg::ref_ptr<osg::Array>, osg::ref_ptr<osg::Array> > ArrayPair;
1304typedef std::vector< ArrayPair > ArrayPairs;
1305static void duplicateArray(ArrayPairs& pairs, osg::ref_ptr<osg::Array>& sourceArray, unsigned int numVertices)
1306{
1307    osg::Array* targetArray = osg::cloneType(sourceArray.get());
1308    targetArray->setBinding(osg::Array::BIND_PER_VERTEX);
1309    targetArray->setNormalize(sourceArray->getNormalize());
1310    targetArray->setPreserveDataType(sourceArray->getPreserveDataType());
1311    targetArray->resizeArray(numVertices);
1312    pairs.push_back(ArrayPair(sourceArray, targetArray));
1313    sourceArray = targetArray;
1314}
1315
1316struct PtrData
1317{
1318    char* source;
1319    char* target;
1320    unsigned int elementSize;
1321
1322    PtrData():source(0),target(0),elementSize(0) {}
1323   
1324    PtrData(osg::Array* s, osg::Array* t):
1325        source(const_cast<char*>(static_cast<const char*>(s->getDataPointer()))),
1326        target(const_cast<char*>(static_cast<const char*>(t->getDataPointer()))),
1327        elementSize(s->getElementSize()) {}
1328       
1329    PtrData(const PtrData& rhs):
1330        source(rhs.source),
1331        target(rhs.target),
1332        elementSize(rhs.elementSize) {}
1333   
1334    PtrData& operator = (const PtrData& rhs)
1335    {
1336        source = rhs.source;
1337        target = rhs.target;
1338        elementSize = rhs.elementSize;
1339        return *this;
1340    }
1341};
1342
1343void Geometry::fixDeprecatedData()
1344{
1345    if (!_containsDeprecatedData) return;
1346   
1347    bool containsBindPerPrimitive = false;
1348   
1349    OSG_NOTICE<<"Geometry::fixDeprecatedData()"<<std::endl;
1350
1351    // copy over attribute arrays.
1352    osg::IndexArray* indices = getIndexArray(_vertexArray.get());
1353    if (indices) setVertexArray(expandIndexArray(_vertexArray.get(), indices));
1354
1355    if (getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE) containsBindPerPrimitive = true;
1356    indices = getIndexArray(_normalArray.get());
1357    if (indices) setNormalArray(expandIndexArray(getNormalArray(), indices));
1358
1359    if (getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE) containsBindPerPrimitive = true;
1360    indices = getIndexArray(_colorArray.get());
1361    if (indices) setColorArray(expandIndexArray(getColorArray(), indices));
1362
1363    if (getSecondaryColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE) containsBindPerPrimitive = true;
1364    indices = getIndexArray(_secondaryColorArray.get());
1365    if (indices) setSecondaryColorArray(expandIndexArray(getSecondaryColorArray(), indices));
1366
1367    if (getFogCoordBinding()==osg::Geometry::BIND_PER_PRIMITIVE) containsBindPerPrimitive = true;
1368    indices = getIndexArray(_fogCoordArray.get());
1369    if (indices) setFogCoordArray(expandIndexArray(getFogCoordArray(), indices));
1370
1371    for(unsigned int ti=0;ti<getNumTexCoordArrays();++ti)
1372    {
1373        indices = getIndexArray(_texCoordList[ti].get());
1374        if (indices) setTexCoordArray(ti, expandIndexArray(getTexCoordArray(ti), indices));
1375    }
1376
1377    for(unsigned int vi=0;vi<_vertexAttribList.size();++vi)
1378    {
1379        if (getVertexAttribBinding(vi)==osg::Geometry::BIND_PER_PRIMITIVE) containsBindPerPrimitive = true;
1380        indices = getIndexArray(_vertexAttribList[vi].get());
1381        if (indices) setVertexAttribArray(vi, expandIndexArray(getVertexAttribArray(vi), indices));
1382    }
1383
1384    // if none of the arrays are bind per primitive our job is done!
1385    if (!containsBindPerPrimitive)
1386    {
1387        _containsDeprecatedData = false;
1388        return;
1389    }   
1390   
1391    // need to expand bind per primitive entries.
1392   
1393    // count how many vertices are required
1394    unsigned int numVertices = 0;
1395    for(PrimitiveSetList::iterator itr = _primitives.begin();
1396        itr != _primitives.end();
1397        ++itr)
1398    {
1399        osg::PrimitiveSet* primitiveset = itr->get();
1400        switch(primitiveset->getType())
1401        {
1402            case(PrimitiveSet::DrawArraysPrimitiveType):
1403            {
1404                const DrawArrays* drawArray = static_cast<const DrawArrays*>(primitiveset);
1405                numVertices = drawArray->getCount();
1406                break;
1407            }
1408            case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
1409            {
1410                const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
1411                for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
1412                    primItr!=drawArrayLengths->end();
1413                    ++primItr)
1414                {
1415                    unsigned int localNumVertices = *primItr;
1416                    numVertices += localNumVertices;
1417                    primItr += localNumVertices;
1418                }
1419                break;
1420            }
1421            case(PrimitiveSet::DrawElementsUBytePrimitiveType):
1422            {
1423                const DrawElementsUByte* drawElements = static_cast<const DrawElementsUByte*>(primitiveset);
1424                numVertices += drawElements->getNumIndices();
1425                break;
1426            }
1427            case(PrimitiveSet::DrawElementsUShortPrimitiveType):
1428            {
1429                const DrawElementsUShort* drawElements = static_cast<const DrawElementsUShort*>(primitiveset);
1430                numVertices += drawElements->getNumIndices();
1431                break;
1432            }
1433            case(PrimitiveSet::DrawElementsUIntPrimitiveType):
1434            {
1435                const DrawElementsUInt* drawElements = static_cast<const DrawElementsUInt*>(primitiveset);
1436                numVertices += drawElements->getNumIndices();
1437                break;
1438            }
1439            default:
1440            {
1441                break;
1442            }
1443        }
1444    }
1445   
1446    // allocate the arrays.
1447    ArrayPairs perVertexArrays;
1448    ArrayPairs perPrimitiveArrays;
1449    if (_vertexArray.valid()) duplicateArray(perVertexArrays, _vertexArray, numVertices);
1450   
1451    if (_normalArray.valid())
1452    {
1453        if (_normalArray->getBinding()==osg::Array::BIND_PER_VERTEX) duplicateArray(perVertexArrays, _normalArray, numVertices);
1454        else if (_normalArray->getBinding()==3 /*osg::Array::BIND_PER_PRIMITIVE*/) duplicateArray(perPrimitiveArrays, _normalArray, numVertices);
1455    }
1456   
1457    if (_colorArray.valid())
1458    {
1459        if (_colorArray->getBinding()==osg::Array::BIND_PER_VERTEX) duplicateArray(perVertexArrays, _colorArray, numVertices);
1460        else if (_colorArray->getBinding()==3 /*osg::Array::BIND_PER_PRIMITIVE*/) duplicateArray(perPrimitiveArrays, _colorArray, numVertices);
1461    }
1462   
1463    if (_secondaryColorArray.valid())
1464    {
1465        if (_secondaryColorArray->getBinding()==osg::Array::BIND_PER_VERTEX) duplicateArray(perVertexArrays, _secondaryColorArray, numVertices);
1466        else if (_secondaryColorArray->getBinding()==3 /*osg::Array::BIND_PER_PRIMITIVE*/) duplicateArray(perPrimitiveArrays, _secondaryColorArray, numVertices);
1467    }
1468   
1469    if (_fogCoordArray.valid())
1470    {
1471        if (_fogCoordArray->getBinding()==osg::Array::BIND_PER_VERTEX) duplicateArray(perVertexArrays, _fogCoordArray, numVertices);
1472        else if (_fogCoordArray->getBinding()==3 /*osg::Array::BIND_PER_PRIMITIVE*/) duplicateArray(perPrimitiveArrays, _fogCoordArray, numVertices);
1473    }
1474   
1475    for(ArrayList::iterator itr = _texCoordList.begin();
1476        itr != _texCoordList.end();
1477        ++itr)
1478    {
1479        if (itr->valid())
1480        {
1481            if ((*itr)->getBinding()==osg::Array::BIND_PER_VERTEX) duplicateArray(perVertexArrays, *itr, numVertices);
1482            else if ((*itr)->getBinding()==3 /*osg::Array::BIND_PER_PRIMITIVE*/) duplicateArray(perPrimitiveArrays, *itr, numVertices);
1483        }
1484    }
1485   
1486    for(ArrayList::iterator itr = _vertexAttribList.begin();
1487        itr != _vertexAttribList.end();
1488        ++itr)
1489    {
1490        if (itr->valid())
1491        {
1492            if ((*itr)->getBinding()==osg::Array::BIND_PER_VERTEX) duplicateArray(perVertexArrays, *itr, numVertices);
1493            else if ((*itr)->getBinding()==3 /*osg::Array::BIND_PER_PRIMITIVE*/) duplicateArray(perPrimitiveArrays, *itr, numVertices);
1494        }
1495    }
1496
1497    typedef std::vector<PtrData> PtrList;
1498    PtrList perVertexPtrs;
1499    PtrList perPrimitivePtrs;
1500   
1501    for(ArrayPairs::iterator itr = perVertexArrays.begin();
1502        itr != perVertexArrays.end();
1503        ++itr)
1504    {
1505        perVertexPtrs.push_back(PtrData(itr->first.get(), itr->second.get()));
1506    }
1507   
1508    for(ArrayPairs::iterator itr = perPrimitiveArrays.begin();
1509        itr != perPrimitiveArrays.end();
1510        ++itr)
1511    {
1512        perPrimitivePtrs.push_back(PtrData(itr->first.get(), itr->second.get()));
1513    }
1514   
1515   
1516    // start the primitiveNum at -1 as we increment it the first time through when
1517    // we start processing the primitive sets.
1518    int primitiveNum = -1;
1519    for(PrimitiveSetList::iterator itr = _primitives.begin();
1520        itr != _primitives.end();
1521        ++itr)
1522    {
1523        osg::PrimitiveSet* primitiveset = itr->get();
1524        GLenum mode=primitiveset->getMode();
1525
1526        unsigned int primLength;
1527        switch(mode)
1528        {
1529            case(GL_POINTS):    primLength=1; break;
1530            case(GL_LINES):     primLength=2; break;
1531            case(GL_TRIANGLES): primLength=3; break;
1532            case(GL_QUADS):     primLength=4; break;
1533            default:            primLength=0; break; // compute later when =0.
1534        }
1535
1536        // copy the vertex data across to the new arays
1537        int source_pindex = -1;
1538        int target_vindex = 0;
1539        switch(primitiveset->getType())
1540        {
1541            case(PrimitiveSet::DrawArraysPrimitiveType):
1542            {
1543                if (primLength==0) primLength=primitiveset->getNumIndices();
1544
1545                const DrawArrays* drawArray = static_cast<const DrawArrays*>(primitiveset);
1546
1547                if (primLength==0) primLength = drawArray->getCount();
1548               
1549                unsigned int primCount=0;
1550                unsigned int indexEnd = drawArray->getFirst()+drawArray->getCount();
1551                for(unsigned int vindex=drawArray->getFirst();
1552                    vindex<indexEnd;
1553                    ++vindex, ++target_vindex, ++primCount)
1554                {
1555                    if ((primCount%primLength)==0) ++source_pindex;
1556                   
1557                    // copy bind per primitive from primitiveNum
1558                    for(PtrList::iterator itr = perVertexPtrs.begin();
1559                        itr != perVertexPtrs.end();
1560                        ++itr)
1561                    {
1562                        PtrData& ptrs = *itr;
1563                        char* source = ptrs.source + vindex*ptrs.elementSize;
1564                        char* target = ptrs.target + target_vindex*ptrs.elementSize;
1565                        for(unsigned int c=0; c<ptrs.elementSize; ++c)
1566                        {
1567                            *target++ = *source++;
1568                        }
1569                    }
1570       
1571                    // copy bind per vertex from vindex
1572                    for(PtrList::iterator itr = perPrimitivePtrs.begin();
1573                        itr != perPrimitivePtrs.end();
1574                        ++itr)
1575                    {
1576                        PtrData& ptrs = *itr;
1577                        char* source = ptrs.source + source_pindex*ptrs.elementSize;
1578                        char* target = ptrs.target + target_vindex*ptrs.elementSize;
1579                        for(unsigned int c=0; c<ptrs.elementSize; ++c)
1580                        {
1581                            *target++ = *source++;
1582                        }
1583                    }
1584                }
1585                break;
1586            }
1587            case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
1588            {
1589                const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
1590                unsigned int vindex=drawArrayLengths->getFirst();
1591                for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
1592                    primItr!=drawArrayLengths->end();
1593                    ++primItr)
1594                {
1595                    unsigned int localPrimLength;
1596                    if (primLength==0) localPrimLength=*primItr;
1597                    else localPrimLength=primLength;
1598
1599                    for(GLsizei primCount=0;
1600                        primCount<*primItr;
1601                        ++vindex, ++target_vindex, ++primCount)
1602                    {
1603                        if ((primCount%localPrimLength)==0) ++source_pindex;
1604                       
1605                        // copy bind per primitive from primitiveNum
1606                        for(PtrList::iterator itr = perVertexPtrs.begin();
1607                            itr != perVertexPtrs.end();
1608                            ++itr)
1609                        {
1610                            PtrData& ptrs = *itr;
1611                            char* source = ptrs.source + vindex*ptrs.elementSize;
1612                            char* target = ptrs.target + target_vindex*ptrs.elementSize;
1613                            for(unsigned int c=0; c<ptrs.elementSize; ++c)
1614                            {
1615                                *target++ = *source++;
1616                            }
1617                        }
1618           
1619                        // copy bind per vertex from vindex
1620                        for(PtrList::iterator itr = perPrimitivePtrs.begin();
1621                            itr != perPrimitivePtrs.end();
1622                            ++itr)
1623                        {
1624                            PtrData& ptrs = *itr;
1625                            char* source = ptrs.source + source_pindex*ptrs.elementSize;
1626                            char* target = ptrs.target + target_vindex*ptrs.elementSize;
1627                            for(unsigned int c=0; c<ptrs.elementSize; ++c)
1628                            {
1629                                *target++ = *source++;
1630                            }
1631                        }
1632                    }
1633                }
1634                break;
1635            }
1636            case(PrimitiveSet::DrawElementsUBytePrimitiveType):
1637            {
1638                if (primLength==0) primLength=primitiveset->getNumIndices();
1639
1640                const DrawElementsUByte* drawElements = static_cast<const DrawElementsUByte*>(primitiveset);
1641                unsigned int primCount=0;
1642                for(DrawElementsUByte::const_iterator primItr=drawElements->begin();
1643                    primItr!=drawElements->end();
1644                    ++primCount, ++target_vindex, ++primItr)
1645                {
1646                    if ((primCount%primLength)==0) ++source_pindex;
1647                    unsigned int vindex=*primItr;
1648                   
1649                    // copy bind per primitive from primitiveNum
1650                    for(PtrList::iterator itr = perVertexPtrs.begin();
1651                        itr != perVertexPtrs.end();
1652                        ++itr)
1653                    {
1654                        PtrData& ptrs = *itr;
1655                        char* source = ptrs.source + vindex*ptrs.elementSize;
1656                        char* target = ptrs.target + target_vindex*ptrs.elementSize;
1657                        for(unsigned int c=0; c<ptrs.elementSize; ++c)
1658                        {
1659                            *target++ = *source++;
1660                        }
1661                    }
1662       
1663                    // copy bind per vertex from vindex
1664                    for(PtrList::iterator itr = perPrimitivePtrs.begin();
1665                        itr != perPrimitivePtrs.end();
1666                        ++itr)
1667                    {
1668                        PtrData& ptrs = *itr;
1669                        char* source = ptrs.source + source_pindex*ptrs.elementSize;
1670                        char* target = ptrs.target + target_vindex*ptrs.elementSize;
1671                        for(unsigned int c=0; c<ptrs.elementSize; ++c)
1672                        {
1673                            *target++ = *source++;
1674                        }
1675                    }
1676                }
1677                break;
1678            }
1679            case(PrimitiveSet::DrawElementsUShortPrimitiveType):
1680            {
1681                if (primLength==0) primLength=primitiveset->getNumIndices();
1682
1683                const DrawElementsUShort* drawElements = static_cast<const DrawElementsUShort*>(primitiveset);
1684                unsigned int primCount=0;
1685                for(DrawElementsUShort::const_iterator primItr=drawElements->begin();
1686                    primItr!=drawElements->end();
1687                    ++primCount, ++target_vindex, ++primItr)
1688                {
1689                    if ((primCount%primLength)==0) ++primitiveNum;
1690                    unsigned int vindex=*primItr;
1691
1692                    // copy bind per primitive from primitiveNum
1693                    for(PtrList::iterator itr = perVertexPtrs.begin();
1694                        itr != perVertexPtrs.end();
1695                        ++itr)
1696                    {
1697                        PtrData& ptrs = *itr;
1698                        char* source = ptrs.source + vindex*ptrs.elementSize;
1699                        char* target = ptrs.target + target_vindex*ptrs.elementSize;
1700                        for(unsigned int c=0; c<ptrs.elementSize; ++c)
1701                        {
1702                            *target++ = *source++;
1703                        }
1704                    }
1705       
1706                    // copy bind per vertex from vindex
1707                    for(PtrList::iterator itr = perPrimitivePtrs.begin();
1708                        itr != perPrimitivePtrs.end();
1709                        ++itr)
1710                    {
1711                        PtrData& ptrs = *itr;
1712                        char* source = ptrs.source + source_pindex*ptrs.elementSize;
1713                        char* target = ptrs.target + target_vindex*ptrs.elementSize;
1714                        for(unsigned int c=0; c<ptrs.elementSize; ++c)
1715                        {
1716                            *target++ = *source++;
1717                        }
1718                    }
1719                }
1720                break;
1721            }
1722            case(PrimitiveSet::DrawElementsUIntPrimitiveType):
1723            {
1724                if (primLength==0) primLength=primitiveset->getNumIndices();
1725
1726                const DrawElementsUInt* drawElements = static_cast<const DrawElementsUInt*>(primitiveset);
1727                unsigned int primCount=0;
1728                for(DrawElementsUInt::const_iterator primItr=drawElements->begin();
1729                    primItr!=drawElements->end();
1730                    ++primCount, ++target_vindex, ++primItr)
1731                {
1732                    if ((primCount%primLength)==0) ++primitiveNum;
1733                    unsigned int vindex=*primItr;
1734
1735                    // copy bind per primitive from primitiveNum
1736                    for(PtrList::iterator itr = perVertexPtrs.begin();
1737                        itr != perVertexPtrs.end();
1738                        ++itr)
1739                    {
1740                        PtrData& ptrs = *itr;
1741                        char* source = ptrs.source + vindex*ptrs.elementSize;
1742                        char* target = ptrs.target + target_vindex*ptrs.elementSize;
1743                        for(unsigned int c=0; c<ptrs.elementSize; ++c)
1744                        {
1745                            *target++ = *source++;
1746                        }
1747                    }
1748       
1749                    // copy bind per vertex from vindex
1750                    for(PtrList::iterator itr = perPrimitivePtrs.begin();
1751                        itr != perPrimitivePtrs.end();
1752                        ++itr)
1753                    {
1754                        PtrData& ptrs = *itr;
1755                        char* source = ptrs.source + source_pindex*ptrs.elementSize;
1756                        char* target = ptrs.target + target_vindex*ptrs.elementSize;
1757                        for(unsigned int c=0; c<ptrs.elementSize; ++c)
1758                        {
1759                            *target++ = *source++;
1760                        }
1761                    }
1762                }
1763                break;
1764            }
1765            default:
1766            {
1767                break;
1768            }
1769        }
1770    }
1771   
1772    _containsDeprecatedData = false;
1773}
Note: See TracBrowser for help on using the browser.