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

Revision 13522, 64.4 kB (checked in by robert, 11 hours ago)

Added in source shaders

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