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 <stdio.h>
14 #include <math.h>
15 #include <float.h>
16 
17 #include <osg/Drawable>
18 #include <osg/State>
19 #include <osg/Notify>
20 #include <osg/Node>
21 #include <osg/GLExtensions>
22 #include <osg/Timer>
23 #include <osg/TriangleFunctor>
24 #include <osg/ContextData>
25 #include <osg/io_utils>
26 
27 #include <algorithm>
28 #include <map>
29 #include <list>
30 
31 #include <OpenThreads/ScopedLock>
32 #include <OpenThreads/Mutex>
33 
34 using namespace osg;
35 
36 static unsigned int s_minimumNumberOfDisplayListsToRetainInCache = 0;
setMinimumNumberOfDisplayListsToRetainInCache(unsigned int minimum)37 void Drawable::setMinimumNumberOfDisplayListsToRetainInCache(unsigned int minimum)
38 {
39     s_minimumNumberOfDisplayListsToRetainInCache = minimum;
40 }
41 
getMinimumNumberOfDisplayListsToRetainInCache()42 unsigned int Drawable::getMinimumNumberOfDisplayListsToRetainInCache()
43 {
44     return s_minimumNumberOfDisplayListsToRetainInCache;
45 }
46 
47 class DisplayListManager : public GraphicsObjectManager
48 {
49 public:
DisplayListManager(unsigned int contextID)50     DisplayListManager(unsigned int contextID):
51         GraphicsObjectManager("DisplayListManager", contextID),
52         _numberDrawablesReusedLastInLastFrame(0),
53         _numberNewDrawablesInLastFrame(0),
54         _numberDeletedDrawablesInLastFrame(0)
55     {
56     }
57 
flushDeletedGLObjects(double,double & availableTime)58     virtual void flushDeletedGLObjects(double, double& availableTime)
59     {
60     #ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
61         // OSG_NOTICE<<"void DisplayListManager::flushDeletedGLObjects(, "<<availableTime<<")"<<std::endl;
62 
63         // if no time available don't try to flush objects.
64         if (availableTime<=0.0) return;
65 
66         const osg::Timer& timer = *osg::Timer::instance();
67         osg::Timer_t start_tick = timer.tick();
68         double elapsedTime = 0.0;
69 
70         unsigned int noDeleted = 0;
71 
72         {
73             OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex_deletedDisplayListCache);
74 
75             unsigned int prev_size = _displayListMap.size();
76 
77             // trim from front
78             DisplayListMap::iterator ditr=_displayListMap.begin();
79             unsigned int maxNumToDelete = (_displayListMap.size() > s_minimumNumberOfDisplayListsToRetainInCache) ? _displayListMap.size()-s_minimumNumberOfDisplayListsToRetainInCache : 0;
80             for(;
81                 ditr!=_displayListMap.end() && elapsedTime<availableTime && noDeleted<maxNumToDelete;
82                 ++ditr)
83             {
84                 glDeleteLists(ditr->second,1);
85 
86                 elapsedTime = timer.delta_s(start_tick,timer.tick());
87                 ++noDeleted;
88 
89                 ++_numberDeletedDrawablesInLastFrame;
90             }
91 
92             if (ditr!=_displayListMap.begin()) _displayListMap.erase(_displayListMap.begin(),ditr);
93 
94             if (noDeleted+_displayListMap.size() != prev_size)
95             {
96                 OSG_WARN<<"Error in delete"<<std::endl;
97             }
98         }
99         elapsedTime = timer.delta_s(start_tick,timer.tick());
100 
101         if (noDeleted!=0) OSG_INFO<<"Number display lists deleted = "<<noDeleted<<" elapsed time"<<elapsedTime<<std::endl;
102 
103         availableTime -= elapsedTime;
104     #else
105         OSG_INFO<<"Warning: Drawable::flushDeletedDisplayLists(..) - not supported."<<std::endl;
106     #endif
107     }
108 
flushAllDeletedGLObjects()109     virtual void flushAllDeletedGLObjects()
110     {
111     #ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
112 
113         OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex_deletedDisplayListCache);
114 
115         for(DisplayListMap::iterator ditr=_displayListMap.begin();
116             ditr!=_displayListMap.end();
117             ++ditr)
118         {
119             glDeleteLists(ditr->second,1);
120         }
121 
122         _displayListMap.clear();
123     #else
124         OSG_INFO<<"Warning: Drawable::deleteDisplayList(..) - not supported."<<std::endl;
125     #endif
126     }
127 
deleteAllGLObjects()128     virtual void deleteAllGLObjects()
129     {
130          OSG_INFO<<"DisplayListManager::deleteAllGLObjects() Not currently implemented"<<std::endl;
131     }
132 
discardAllGLObjects()133     virtual void discardAllGLObjects()
134     {
135         OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex_deletedDisplayListCache);
136         _displayListMap.clear();
137     }
138 
deleteDisplayList(GLuint globj,unsigned int sizeHint)139     void deleteDisplayList(GLuint globj, unsigned int sizeHint)
140     {
141     #ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
142         if (globj!=0)
143         {
144             OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex_deletedDisplayListCache);
145 
146             // insert the globj into the cache for the appropriate context.
147             _displayListMap.insert(DisplayListMap::value_type(sizeHint,globj));
148         }
149     #else
150         OSG_INFO<<"Warning: Drawable::deleteDisplayList(..) - not supported."<<std::endl;
151     #endif
152     }
153 
generateDisplayList(unsigned int sizeHint)154     GLuint generateDisplayList(unsigned int sizeHint)
155     {
156     #ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
157         OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex_deletedDisplayListCache);
158 
159         if (_displayListMap.empty())
160         {
161             ++_numberNewDrawablesInLastFrame;
162             return  glGenLists( 1 );
163         }
164         else
165         {
166             DisplayListMap::iterator itr = _displayListMap.lower_bound(sizeHint);
167             if (itr!=_displayListMap.end())
168             {
169                 // OSG_NOTICE<<"Reusing a display list of size = "<<itr->first<<" for requested size = "<<sizeHint<<std::endl;
170 
171                 ++_numberDrawablesReusedLastInLastFrame;
172 
173                 GLuint globj = itr->second;
174                 _displayListMap.erase(itr);
175 
176                 return globj;
177             }
178             else
179             {
180                 // OSG_NOTICE<<"Creating a new display list of size = "<<sizeHint<<" although "<<_displayListMap.size()<<" are available"<<std::endl;
181                 ++_numberNewDrawablesInLastFrame;
182                 return  glGenLists( 1 );
183             }
184         }
185     #else
186         OSG_INFO<<"Warning: Drawable::generateDisplayList(..) - not supported."<<std::endl;
187         return 0;
188     #endif
189     }
190 
191 protected:
192 
193     int _numberDrawablesReusedLastInLastFrame;
194     int _numberNewDrawablesInLastFrame;
195     int _numberDeletedDrawablesInLastFrame;
196 
197     typedef std::multimap<unsigned int,GLuint> DisplayListMap;
198     OpenThreads::Mutex _mutex_deletedDisplayListCache;
199     DisplayListMap _displayListMap;
200 
201 };
202 
generateDisplayList(unsigned int contextID,unsigned int sizeHint)203 GLuint Drawable::generateDisplayList(unsigned int contextID, unsigned int sizeHint)
204 {
205     return osg::get<DisplayListManager>(contextID)->generateDisplayList(sizeHint);
206 }
207 
deleteDisplayList(unsigned int contextID,GLuint globj,unsigned int sizeHint)208 void Drawable::deleteDisplayList(unsigned int contextID,GLuint globj, unsigned int sizeHint)
209 {
210     osg::get<DisplayListManager>(contextID)->deleteDisplayList(globj, sizeHint);
211 }
212 
213 
Drawable()214 Drawable::Drawable()
215 {
216     // Note, if your are defining a subclass from drawable which is
217     // dynamically updated then you should set both the following to
218     // to false in your constructor.  This will prevent any display
219     // lists from being automatically created and safeguard the
220     // dynamic updating of data.
221 #ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
222     _supportsDisplayList = true;
223     _useDisplayList = true;
224 #else
225     _supportsDisplayList = false;
226     _useDisplayList = false;
227 #endif
228 
229 #if 0
230     _supportsVertexBufferObjects = false;
231     //_useVertexBufferObjects = false;
232     _useVertexBufferObjects = false;
233 #else
234     _supportsVertexBufferObjects = true;
235     _useVertexBufferObjects = true;
236 #endif
237 
238     _useVertexArrayObject = false;
239 }
240 
Drawable(const Drawable & drawable,const CopyOp & copyop)241 Drawable::Drawable(const Drawable& drawable,const CopyOp& copyop):
242     Node(drawable,copyop),
243     _initialBoundingBox(drawable._initialBoundingBox),
244     _computeBoundingBoxCallback(drawable._computeBoundingBoxCallback),
245     _boundingBox(drawable._boundingBox),
246     _shape(copyop(drawable._shape.get())),
247     _supportsDisplayList(drawable._supportsDisplayList),
248     _useDisplayList(drawable._useDisplayList),
249     _supportsVertexBufferObjects(drawable._supportsVertexBufferObjects),
250     _useVertexBufferObjects(drawable._useVertexBufferObjects),
251     _useVertexArrayObject(drawable._useVertexArrayObject),
252     _drawCallback(drawable._drawCallback),
253     _createVertexArrayStateCallback(drawable._createVertexArrayStateCallback)
254 {
255 }
256 
~Drawable()257 Drawable::~Drawable()
258 {
259     // clean up display lists if assigned, for the display lists size  we can't use glGLObjectSizeHint() as it's a virtual function, so have to default to a 0 size hint.
260     #ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
261     for(unsigned int i=0;i<_globjList.size();++i)
262     {
263         if (_globjList[i] != 0)
264         {
265             Drawable::deleteDisplayList(i,_globjList[i], 0); // we don't know getGLObjectSizeHint()
266             _globjList[i] = 0;
267         }
268     }
269     #endif
270 
271     // clean up VertexArrayState
272     for(unsigned int i=0; i<_vertexArrayStateList.size(); ++i)
273     {
274         VertexArrayState* vas = _vertexArrayStateList[i].get();
275         if (vas)
276         {
277             vas->release();
278             _vertexArrayStateList[i] = 0;
279         }
280     }
281 }
282 
getWorldMatrices(const osg::Node * haltTraversalAtNode) const283 osg::MatrixList Drawable::getWorldMatrices(const osg::Node* haltTraversalAtNode) const
284 {
285     osg::MatrixList matrices;
286     for(ParentList::const_iterator itr = _parents.begin();
287         itr != _parents.end();
288         ++itr)
289     {
290         osg::MatrixList localMatrices = (*itr)->getWorldMatrices(haltTraversalAtNode);
291         matrices.insert(matrices.end(), localMatrices.begin(), localMatrices.end());
292     }
293     return matrices;
294 }
295 
computeDataVariance()296 void Drawable::computeDataVariance()
297 {
298     if (getDataVariance() != UNSPECIFIED) return;
299 
300     bool dynamic = false;
301 
302     if (getUpdateCallback() ||
303         getEventCallback() ||
304         getCullCallback())
305     {
306         dynamic = true;
307     }
308 
309     setDataVariance(dynamic ? DYNAMIC : STATIC);
310 }
311 
setThreadSafeRefUnref(bool threadSafe)312 void Drawable::setThreadSafeRefUnref(bool threadSafe)
313 {
314     Object::setThreadSafeRefUnref(threadSafe);
315 
316     if (_stateset.valid()) _stateset->setThreadSafeRefUnref(threadSafe);
317     if (_drawCallback.valid()) _drawCallback->setThreadSafeRefUnref(threadSafe);
318 }
319 
resizeGLObjectBuffers(unsigned int maxSize)320 void Drawable::resizeGLObjectBuffers(unsigned int maxSize)
321 {
322     if (_stateset.valid()) _stateset->resizeGLObjectBuffers(maxSize);
323     if (_drawCallback.valid()) _drawCallback->resizeGLObjectBuffers(maxSize);
324 
325     _globjList.resize(maxSize);
326 
327     _vertexArrayStateList.resize(maxSize);
328 }
329 
releaseGLObjects(State * state) const330 void Drawable::releaseGLObjects(State* state) const
331 {
332     if (_stateset.valid()) _stateset->releaseGLObjects(state);
333 
334     if (_drawCallback.valid()) _drawCallback->releaseGLObjects(state);
335 
336     if (state)
337     {
338         // get the contextID (user defined ID of 0 upwards) for the
339         // current OpenGL context.
340         unsigned int contextID = state->getContextID();
341 
342     #ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
343         if (_useDisplayList)
344         {
345             // get the globj for the current contextID.
346             GLuint& globj = _globjList[contextID];
347 
348             // call the globj if already set otherwise compile and execute.
349             if( globj != 0 )
350             {
351                 Drawable::deleteDisplayList(contextID,globj, getGLObjectSizeHint());
352                 globj = 0;
353             }
354         }
355     #endif
356 
357         VertexArrayState* vas = contextID <_vertexArrayStateList.size() ? _vertexArrayStateList[contextID].get() : 0;
358         if (vas)
359         {
360             vas->release();
361             _vertexArrayStateList[contextID] = 0;
362         }
363     }
364     else
365     {
366     #ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
367         for(unsigned int i=0;i<_globjList.size();++i)
368         {
369             if (_globjList[i] != 0)
370             {
371                 Drawable::deleteDisplayList(i,_globjList[i], getGLObjectSizeHint());
372                 _globjList[i] = 0;
373             }
374         }
375     #endif
376 
377         for(unsigned int i=0; i<_vertexArrayStateList.size(); ++i)
378         {
379             VertexArrayState* vas = _vertexArrayStateList[i].get();
380             if (vas)
381             {
382                 vas->release();
383                 _vertexArrayStateList[i] = 0;
384             }
385         }
386     }
387 }
388 
setSupportsDisplayList(bool flag)389 void Drawable::setSupportsDisplayList(bool flag)
390 {
391     // if value unchanged simply return.
392     if (_supportsDisplayList==flag) return;
393 
394 #ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
395     // if previously set to true then need to check about display lists.
396     if (_supportsDisplayList)
397     {
398         if (_useDisplayList)
399         {
400             // used to support display lists and display lists switched
401             // on so now delete them and turn useDisplayList off.
402             dirtyGLObjects();
403             _useDisplayList = false;
404         }
405     }
406 
407     // set with new value.
408     _supportsDisplayList=flag;
409 #else
410     _supportsDisplayList=false;
411 #endif
412 }
413 
setUseDisplayList(bool flag)414 void Drawable::setUseDisplayList(bool flag)
415 {
416     // if value unchanged simply return.
417     if (_useDisplayList==flag) return;
418 
419 #ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
420     // if was previously set to true, remove display list.
421 
422     if (_useDisplayList)
423     {
424         dirtyGLObjects();
425     }
426 
427     if (_supportsDisplayList)
428     {
429 
430         // set with new value.
431         _useDisplayList = flag;
432 
433     }
434     else // does not support display lists.
435     {
436         if (flag)
437         {
438             OSG_WARN<<"Warning: attempt to setUseDisplayList(true) on a drawable with does not support display lists."<<std::endl;
439         }
440         else
441         {
442             // set with new value.
443             _useDisplayList = false;
444         }
445     }
446 #else
447    _useDisplayList = false;
448 #endif
449 }
450 
451 
setUseVertexArrayObject(bool flag)452 void Drawable::setUseVertexArrayObject(bool flag)
453 {
454     _useVertexArrayObject = flag;
455 }
456 
457 
458 
setUseVertexBufferObjects(bool flag)459 void Drawable::setUseVertexBufferObjects(bool flag)
460 {
461     // _useVertexBufferObjects = true;
462 
463     // OSG_NOTICE<<"Drawable::setUseVertexBufferObjects("<<flag<<")"<<std::endl;
464 
465     // if value unchanged simply return.
466     if (_useVertexBufferObjects==flag) return;
467 
468     // if was previously set to true, remove display list.
469     if (_useVertexBufferObjects)
470     {
471         dirtyGLObjects();
472     }
473 
474     _useVertexBufferObjects = flag;
475 }
476 
dirtyGLObjects()477 void Drawable::dirtyGLObjects()
478 {
479 #ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
480     for(unsigned int i=0;i<_globjList.size();++i)
481     {
482         if (_globjList[i] != 0)
483         {
484             Drawable::deleteDisplayList(i,_globjList[i], getGLObjectSizeHint());
485             _globjList[i] = 0;
486         }
487     }
488 #endif
489 
490     for(unsigned int i=0; i<_vertexArrayStateList.size(); ++i)
491     {
492         VertexArrayState* vas = _vertexArrayStateList[i].get();
493         if (vas) vas->dirty();
494     }
495 }
496 
497 
498 struct ComputeBound : public PrimitiveFunctor
499 {
ComputeBoundComputeBound500         ComputeBound()
501         {
502             _vertices2f = 0;
503             _vertices3f = 0;
504             _vertices4f = 0;
505             _vertices2d = 0;
506             _vertices3d = 0;
507             _vertices4d = 0;
508         }
509 
setVertexArrayComputeBound510         virtual void setVertexArray(unsigned int,const Vec2* vertices) { _vertices2f = vertices; }
setVertexArrayComputeBound511         virtual void setVertexArray(unsigned int,const Vec3* vertices) { _vertices3f = vertices; }
setVertexArrayComputeBound512         virtual void setVertexArray(unsigned int,const Vec4* vertices) { _vertices4f = vertices; }
513 
setVertexArrayComputeBound514         virtual void setVertexArray(unsigned int,const Vec2d* vertices) { _vertices2d  = vertices; }
setVertexArrayComputeBound515         virtual void setVertexArray(unsigned int,const Vec3d* vertices) { _vertices3d  = vertices; }
setVertexArrayComputeBound516         virtual void setVertexArray(unsigned int,const Vec4d* vertices) { _vertices4d = vertices; }
517 
518         template<typename T>
_drawArraysComputeBound519         void _drawArrays(T* vert, T* end)
520         {
521             for(;vert<end;++vert)
522             {
523                 vertex(*vert);
524             }
525         }
526 
527 
528         template<typename T, typename I>
_drawElementsComputeBound529         void _drawElements(T* vert, I* indices, I* end)
530         {
531             for(;indices<end;++indices)
532             {
533                 vertex(vert[*indices]);
534             }
535         }
536 
drawArraysComputeBound537         virtual void drawArrays(GLenum,GLint first,GLsizei count)
538         {
539             if      (_vertices3f) _drawArrays(_vertices3f+first, _vertices3f+(first+count));
540             else if (_vertices2f) _drawArrays(_vertices2f+first, _vertices2f+(first+count));
541             else if (_vertices4f) _drawArrays(_vertices4f+first, _vertices4f+(first+count));
542             else if (_vertices2d) _drawArrays(_vertices2d+first, _vertices2d+(first+count));
543             else if (_vertices3d) _drawArrays(_vertices3d+first, _vertices3d+(first+count));
544             else if (_vertices4d) _drawArrays(_vertices4d+first, _vertices4d+(first+count));
545         }
546 
drawElementsComputeBound547         virtual void drawElements(GLenum,GLsizei count,const GLubyte* indices)
548         {
549             if (_vertices3f) _drawElements(_vertices3f, indices, indices + count);
550             else if (_vertices2f) _drawElements(_vertices2f, indices, indices + count);
551             else if (_vertices4f) _drawElements(_vertices4f, indices, indices + count);
552             else if (_vertices2d) _drawElements(_vertices2d, indices, indices + count);
553             else if (_vertices3d) _drawElements(_vertices3d, indices, indices + count);
554             else if (_vertices4d) _drawElements(_vertices4d, indices, indices + count);
555         }
556 
drawElementsComputeBound557         virtual void drawElements(GLenum,GLsizei count,const GLushort* indices)
558         {
559             if      (_vertices3f) _drawElements(_vertices3f, indices, indices + count);
560             else if (_vertices2f) _drawElements(_vertices2f, indices, indices + count);
561             else if (_vertices4f) _drawElements(_vertices4f, indices, indices + count);
562             else if (_vertices2d) _drawElements(_vertices2d, indices, indices + count);
563             else if (_vertices3d) _drawElements(_vertices3d, indices, indices + count);
564             else if (_vertices4d) _drawElements(_vertices4d, indices, indices + count);
565         }
566 
drawElementsComputeBound567         virtual void drawElements(GLenum,GLsizei count,const GLuint* indices)
568         {
569             if      (_vertices3f) _drawElements(_vertices3f, indices, indices + count);
570             else if (_vertices2f) _drawElements(_vertices2f, indices, indices + count);
571             else if (_vertices4f) _drawElements(_vertices4f, indices, indices + count);
572             else if (_vertices2d) _drawElements(_vertices2d, indices, indices + count);
573             else if (_vertices3d) _drawElements(_vertices3d, indices, indices + count);
574             else if (_vertices4d) _drawElements(_vertices4d, indices, indices + count);
575         }
576 
beginComputeBound577         virtual void begin(GLenum) {}
vertexComputeBound578         virtual void vertex(const Vec2& vert) { _bb.expandBy(osg::Vec3(vert[0],vert[1],0.0f)); }
vertexComputeBound579         virtual void vertex(const Vec3& vert) { _bb.expandBy(vert); }
vertexComputeBound580         virtual void vertex(const Vec4& vert) { if (vert[3]!=0.0f) _bb.expandBy(osg::Vec3(vert[0],vert[1],vert[2])/vert[3]); }
vertexComputeBound581         virtual void vertex(const Vec2d& vert) { _bb.expandBy(osg::Vec3(vert[0],vert[1],0.0f)); }
vertexComputeBound582         virtual void vertex(const Vec3d& vert) { _bb.expandBy(vert); }
vertexComputeBound583         virtual void vertex(const Vec4d& vert) { if (vert[3]!=0.0f) _bb.expandBy(osg::Vec3(vert[0],vert[1],vert[2])/vert[3]); }
vertexComputeBound584         virtual void vertex(float x,float y)  { _bb.expandBy(x,y,1.0f); }
vertexComputeBound585         virtual void vertex(float x,float y,float z) { _bb.expandBy(x,y,z); }
vertexComputeBound586         virtual void vertex(float x,float y,float z,float w) { if (w!=0.0f) _bb.expandBy(x/w,y/w,z/w); }
vertexComputeBound587         virtual void vertex(double x,double y)  { _bb.expandBy(x,y,1.0f); }
vertexComputeBound588         virtual void vertex(double x,double y,double z) { _bb.expandBy(x,y,z); }
vertexComputeBound589         virtual void vertex(double x,double y,double z,double w) { if (w!=0.0f) _bb.expandBy(x/w,y/w,z/w); }
endComputeBound590         virtual void end() {}
591 
592         const Vec2*     _vertices2f;
593         const Vec3*     _vertices3f;
594         const Vec4*     _vertices4f;
595         const Vec2d*    _vertices2d;
596         const Vec3d*    _vertices3d;
597         const Vec4d*    _vertices4d;
598         BoundingBox     _bb;
599 };
600 
computeBound() const601 BoundingSphere Drawable::computeBound() const
602 {
603     return BoundingSphere(getBoundingBox());
604 }
605 
computeBoundingBox() const606 BoundingBox Drawable::computeBoundingBox() const
607 {
608     ComputeBound cb;
609 
610     Drawable* non_const_this = const_cast<Drawable*>(this);
611     non_const_this->accept(cb);
612 
613 #if 0
614     OSG_NOTICE<<"computeBound() "<<cb._bb.xMin()<<", "<<cb._bb.xMax()<<", "<<std::endl;
615     OSG_NOTICE<<"               "<<cb._bb.yMin()<<", "<<cb._bb.yMax()<<", "<<std::endl;
616     OSG_NOTICE<<"               "<<cb._bb.zMin()<<", "<<cb._bb.zMax()<<", "<<std::endl;
617 #endif
618 
619     return cb._bb;
620 }
621 
setBound(const BoundingBox & bb) const622 void Drawable::setBound(const BoundingBox& bb) const
623 {
624      _boundingBox = bb;
625      _boundingSphere = computeBound();
626      _boundingSphereComputed = true;
627 }
628 
629 
compileGLObjects(RenderInfo & renderInfo) const630 void Drawable::compileGLObjects(RenderInfo& renderInfo) const
631 {
632 
633 #ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
634     if (!renderInfo.getState()->useVertexBufferObject(_supportsVertexBufferObjects && _useVertexBufferObjects) && _useDisplayList)
635     {
636         // get the contextID (user defined ID of 0 upwards) for the
637         // current OpenGL context.
638         unsigned int contextID = renderInfo.getContextID();
639 
640         // get the globj for the current contextID.
641         GLuint& globj = _globjList[contextID];
642 
643         // call the globj if already set otherwise compile and execute.
644         if( globj != 0 )
645         {
646             glDeleteLists( globj, 1 );
647         }
648 
649         globj = generateDisplayList(contextID, getGLObjectSizeHint());
650         glNewList( globj, GL_COMPILE );
651 
652         drawInner(renderInfo);
653 
654         glEndList();
655     }
656 #endif
657 }
658 
659 #ifndef INLINE_DRAWABLE_DRAW
660 
draw(RenderInfo & renderInfo) const661 void Drawable::draw(RenderInfo& renderInfo) const
662 {
663     State& state = *renderInfo.getState();
664     bool useVertexArrayObject = state.useVertexArrayObject(_useVertexArrayObject);
665     if (useVertexArrayObject)
666     {
667         unsigned int contextID = renderInfo.getContextID();
668 
669         VertexArrayState* vas = _vertexArrayStateList[contextID].get();
670         if (!vas)
671         {
672             _vertexArrayStateList[contextID] = vas = createVertexArrayState(renderInfo);
673         }
674         else
675         {
676             // vas->setRequiresSetArrays(getDataVariance()==osg::Object::DYNAMIC);
677         }
678 
679         State::SetCurrentVertexArrayStateProxy setVASProxy(state, vas);
680 
681         state.bindVertexArrayObject(vas);
682 
683         drawInner(renderInfo);
684 
685         vas->setRequiresSetArrays(getDataVariance()==osg::Object::DYNAMIC);
686 
687         return;
688     }
689 
690     // TODO, add check against whether VAO is active and supported
691     if (state.getCurrentVertexArrayState())
692     {
693         //OSG_NOTICE<<"state.getCurrentVertexArrayState()->getVertexArrayObject()="<< state.getCurrentVertexArrayState()->getVertexArrayObject()<<std::endl;
694         state.bindVertexArrayObject(state.getCurrentVertexArrayState());
695     }
696 
697 
698 #ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
699     if (!state.useVertexBufferObject(_supportsVertexBufferObjects && _useVertexBufferObjects) && _useDisplayList)
700     {
701         // get the contextID (user defined ID of 0 upwards) for the
702         // current OpenGL context.
703         unsigned int contextID = renderInfo.getContextID();
704 
705         // get the globj for the current contextID.
706         GLuint& globj = _globjList[contextID];
707 
708         if( globj == 0 )
709         {
710             // compile the display list
711             globj = generateDisplayList(contextID, getGLObjectSizeHint());
712             glNewList( globj, GL_COMPILE );
713 
714             drawInner(renderInfo);
715 
716             glEndList();
717         }
718 
719         // call the display list
720         glCallList( globj);
721     }
722     else
723 #endif
724     {
725         // if state.previousVertexArrayState() is different than currentVertexArrayState bind current
726 
727         // OSG_NOTICE<<"Fallback drawInner()........................"<<std::endl;
728 
729         drawInner(renderInfo);
730     }
731 }
732 
733 #endif
734 
createVertexArrayStateImplementation(RenderInfo & renderInfo) const735 VertexArrayState* Drawable::createVertexArrayStateImplementation(RenderInfo& renderInfo) const
736 {
737     OSG_INFO<<"VertexArrayState* Drawable::createVertexArrayStateImplementation(RenderInfo& renderInfo) const "<<this<<std::endl;
738     VertexArrayState* vos = new osg::VertexArrayState(renderInfo.getState());
739     vos->assignAllDispatchers();
740     return vos;
741 }
742