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

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

From Mattias Helsing, "Seems I was only half right given what you asked for. CMP0017 only
says that modules that are found and ran from cmake modules dir should
prefer cmake-provided modules. find_package() and include() still look
in CMAKE_MODULE_PATH first.

After some investigating I've come up with a proposal examplified in
the attached FindGDAL.cmake script. It simply calls the cmake provided
FindGDAL.cmake if it exists and returns if it succeeds in finding GDAL
using that, otherwise continue with our local cmake code.
Pro: Wont clutter our root CMakeLists.txt
Con: If we begin to write more advanced Findxxx modules (using
COMPONENTS, REQUIRED etc.) we may have to revise this scheme.
"

  • 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.