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