openscenegraph
Drawable
Go to the documentation of this file.
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
14#ifndef OSG_DRAWABLE
15#define OSG_DRAWABLE 1
16
17#include <osg/BoundingBox>
18#include <osg/Shape>
19#include <osg/BufferObject>
20#include <osg/PrimitiveSet>
21#include <osg/RenderInfo>
22#include <osg/Group>
23
24
25#ifndef GL_NV_occlusion_query
26
27 #define GL_OCCLUSION_TEST_HP 0x8165
28 #define GL_OCCLUSION_TEST_RESULT_HP 0x8166
29 #define GL_PIXEL_COUNTER_BITS_NV 0x8864
30 #define GL_CURRENT_OCCLUSION_QUERY_ID_NV 0x8865
31 #define GL_PIXEL_COUNT_NV 0x8866
32 #define GL_PIXEL_COUNT_AVAILABLE_NV 0x8867
33
34#endif
35
36#ifndef GL_ARB_occlusion_query
37
38 #define GL_SAMPLES_PASSED_ARB 0x8914
39 #define GL_QUERY_COUNTER_BITS_ARB 0x8864
40 #define GL_CURRENT_QUERY_ARB 0x8865
41 #define GL_QUERY_RESULT_ARB 0x8866
42 #define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867
43
44#endif
45
46
47#ifndef GL_TIME_ELAPSED
48 #define GL_TIME_ELAPSED 0x88BF
49 #define GL_TIMESTAMP 0x8E28
50#endif
51
52#ifndef GL_QUERY_RESULT
53 #define GL_QUERY_RESULT 0x8866
54 #define GL_QUERY_RESULT_AVAILABLE 0x8867
55#endif
56
57
58#define INLINE_DRAWABLE_DRAW
59
60namespace osg {
61
62
63class Vec2f;
64class Vec3f;
65class Vec4f;
66class Vec4ub;
67class Geometry;
68class NodeVisitor;
69class ArrayDispatchers;
70
71/** Pure virtual base class for drawable geometry. In OSG, everything that can
72 * be rendered is implemented as a class derived from \c Drawable. The
73 * \c Drawable class contains no drawing primitives, since these are provided
74 * by subclasses such as \c osg::Geometry.
75 * <p>Notice that a \c Drawable is not a \c Node, and therefore it cannot be
76 * directly added to a scene graph. Instead, <tt>Drawable</tt>s are attached to
77 * <tt>Geode</tt>s, which are scene graph nodes.
78 * <p>The OpenGL state that must be used when rendering a \c Drawable is
79 * represented by a \c StateSet. Since a \c Drawable has a reference
80 * (\c osg::ref_ptr) to a \c StateSet, <tt>StateSet</tt>s can be shared between
81 * different <tt>Drawable</tt>s. In fact, sharing <tt>StateSet</tt>s is a good
82 * way to improve performance, since this allows OSG to reduce the number of
83 * expensive changes in the OpenGL state.
84 * <p>Finally, <tt>Drawable</tt>s can also be shared between different
85 * <tt>Geode</tt>s, so that the same geometry (loaded to memory just once) can
86 * be used in different parts of the scene graph.
87*/
88class OSG_EXPORT Drawable : public Node
89{
90 public:
91
92 Drawable();
93
94 /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
95 Drawable(const Drawable& drawable,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
96
97 META_Node(osg, Drawable);
98
99 /** Convert 'this' into a Drawable pointer if Object is a Drawable, otherwise return 0.
100 * Equivalent to dynamic_cast<Drawable*>(this).*/
101 virtual Drawable* asDrawable() { return this; }
102
103 /** convert 'const this' into a const Drawable pointer if Object is a Drawable, otherwise return 0.
104 * Equivalent to dynamic_cast<const Drawable*>(this).*/
105 virtual const Drawable* asDrawable() const { return this; }
106
107 /** Compute the DataVariance based on an assessment of callback etc.*/
108 virtual void computeDataVariance();
109
110 /** Get the list of matrices that transform this node from local coordinates to world coordinates.
111 * The optional Node* haltTraversalAtNode allows the user to prevent traversal beyond a specified node. */
112 MatrixList getWorldMatrices(const osg::Node* haltTraversalAtNode=0) const;
113
114
115 /** Set the initial bounding volume to use when computing the overall bounding volume.*/
116 void setInitialBound(const osg::BoundingBox& bbox) { _initialBoundingBox = bbox; dirtyBound(); }
117
118 /** Set the initial bounding volume to use when computing the overall bounding volume.*/
119 const BoundingBox& getInitialBound() const { return _initialBoundingBox; }
120
121 inline const BoundingSphere& getBound() const
122 {
123 if(!_boundingSphereComputed) getBoundingBox();
124 return _boundingSphere;
125 }
126
127 /** Get BoundingBox of Drawable.
128 * If the BoundingBox is not up to date then its updated via an internal call to computeBond().
129 */
130 inline const BoundingBox& getBoundingBox() const
131 {
132 if(!_boundingSphereComputed)
133 {
134 _boundingBox = _initialBoundingBox;
135
136 if (_computeBoundingBoxCallback.valid())
137 _boundingBox.expandBy(_computeBoundingBoxCallback->computeBound(*this));
138 else
139 _boundingBox.expandBy(computeBoundingBox());
140
141 if(_boundingBox.valid()){
142 _boundingSphere.set(_boundingBox.center(), _boundingBox.radius());
143 } else {
144 _boundingSphere.init();
145 }
146
147 _boundingSphereComputed = true;
148 }
149
150 return _boundingBox;
151 }
152
153
154 /** Compute the bounding sphere around Drawables's geometry.*/
155 virtual BoundingSphere computeBound() const;
156
157 /** Compute the bounding box around Drawables's geometry.*/
158 virtual BoundingBox computeBoundingBox() const;
159
160 /** Callback to allow users to override the default computation of bounding volume. */
161 struct ComputeBoundingBoxCallback : public osg::Object
162 {
163 ComputeBoundingBoxCallback() {}
164
165 ComputeBoundingBoxCallback(const ComputeBoundingBoxCallback& org,const CopyOp& copyop):
166 Object(org, copyop) {}
167
168 META_Object(osg,ComputeBoundingBoxCallback);
169
170 virtual BoundingBox computeBound(const osg::Drawable&) const { return BoundingBox(); }
171 };
172
173 /** Set the compute bound callback to override the default computeBound.*/
174 void setComputeBoundingBoxCallback(ComputeBoundingBoxCallback* callback) { _computeBoundingBoxCallback = callback; }
175
176 /** Get the compute bound callback.*/
177 ComputeBoundingBoxCallback* getComputeBoundingBoxCallback() { return _computeBoundingBoxCallback.get(); }
178
179 /** Get the const compute bound callback.*/
180 const ComputeBoundingBoxCallback* getComputeBoundingBoxCallback() const { return _computeBoundingBoxCallback.get(); }
181
182
183 /** Set the Shape of the \c Drawable. The shape can be used to
184 * speed up collision detection or as a guide for procedural
185 * geometry generation.
186 * @see osg::Shape.
187 */
188 virtual void setShape(Shape* shape) { _shape = shape; }
189
190 template<class T> void setShape(const ref_ptr<T>& shape) { setShape(shape.get()); }
191
192 /** Get the Shape of the Drawable.*/
193 inline Shape* getShape() { return _shape.get(); }
194
195 /** Get the const Shape of the const Drawable.*/
196 inline const Shape* getShape() const { return _shape.get(); }
197
198
199
200 /** Set the drawable so that it can or cannot be used in conjunction with OpenGL
201 * display lists. When set to true, calls to Drawable::setUseDisplayList,
202 * whereas when set to false, no display lists can be created and calls
203 * to setUseDisplayList are ignored, and a warning is produced. The latter
204 * is typically used to guard against the switching on of display lists
205 * on objects with dynamic internal data such as continuous Level of Detail
206 * algorithms.*/
207 void setSupportsDisplayList(bool flag);
208
209 /** Get whether display lists are supported for this drawable instance.*/
210 inline bool getSupportsDisplayList() const { return _supportsDisplayList; }
211
212
213 /** When set to true, force the draw method to use OpenGL Display List for rendering.
214 If false, rendering directly. If the display list has not been compiled
215 already, the next call to draw will automatically create the display list.*/
216 void setUseDisplayList(bool flag);
217
218 /** Return whether OpenGL display lists are being used for rendering.*/
219 inline bool getUseDisplayList() const { return _useDisplayList; }
220
221 /** Return OpenGL display list for specified contextID. */
222 inline GLuint& getDisplayList(unsigned int contextID) const { return _globjList[contextID]; }
223
224 /** When set to true, ignore the setUseDisplayList() settings, and hints to the drawImplementation
225 method to use OpenGL vertex buffer objects for rendering.*/
226 virtual void setUseVertexBufferObjects(bool flag);
227
228 /** Return whether OpenGL vertex buffer objects should be used when supported by OpenGL driver.*/
229 inline bool getUseVertexBufferObjects() const { return _useVertexBufferObjects; }
230
231
232 /** Set whether to use a local VertexArrayObject for this Drawable.*/
233 void setUseVertexArrayObject(bool flag);
234
235 /** Return whether to use a local VertexArrayObject for this Drawable.*/
236 bool getUseVertexArrayObject() const { return _useVertexArrayObject; }
237
238#ifdef OSG_USE_DEPRECATED_API
239 /** Deprecated, use dirtyGLObjects() instead. */
240 inline void dirtyDisplayList()
241 {
242 dirtyGLObjects();
243 }
244#endif
245
246 /** Force a recompile on next draw() of any OpenGL objects associated with this geoset.*/
247 virtual void dirtyGLObjects();
248
249
250 /** Return the estimated size of GLObjects (display lists/vertex buffer objects) that are associated with this drawable.
251 * This size is used a hint for reuse of deleted display lists/vertex buffer objects. */
252 virtual unsigned int getGLObjectSizeHint() const { return 0; }
253
254
255
256 /** Draw OpenGL primitives.
257 * If the \c Drawable has \c _useDisplayList set to \c true, then use
258 * an OpenGL display list, automatically compiling one if required.
259 * Otherwise, call \c drawImplementation().
260 * @note This method should \e not be overridden in subclasses, as it
261 * manages the optional display list (notice this is not even
262 * \c virtual). Subclasses should override
263 * \c drawImplementation() instead.
264 */
265#ifdef INLINE_DRAWABLE_DRAW
266 inline void draw(RenderInfo& renderInfo) const;
267#else
268 void draw(RenderInfo& renderInfo) const;
269#endif
270
271 inline void drawInner(RenderInfo& renderInfo) const
272 {
273 if (_drawCallback.valid())
274 _drawCallback->drawImplementation(renderInfo,this);
275 else
276 drawImplementation(renderInfo);
277 }
278
279
280 /** Immediately compile this \c Drawable into an OpenGL Display List/VertexBufferObjects.
281 * @note Operation is ignored if \c _useDisplayList is \c false or VertexBufferObjects are not used.
282 */
283 virtual void compileGLObjects(RenderInfo& renderInfo) const;
284
285
286 /** Callback class for overriding the default Drawable::createCreateVertexArrayStateImplementation().*/
287 struct CreateVertexArrayStateCallback : public virtual osg::Object
288 {
289 CreateVertexArrayStateCallback() {}
290
291 CreateVertexArrayStateCallback(const CreateVertexArrayStateCallback& rhs,const CopyOp& copyop):
292 Object(rhs, copyop) {}
293
294 META_Object(osg, CreateVertexArrayStateCallback);
295
296 /** do customized createVertexArrayState .*/
297 virtual osg::VertexArrayState* createVertexArrayStateImplementation(osg::RenderInfo& renderInfo, const osg::Drawable* drawable) const
298 {
299 return drawable->createVertexArrayStateImplementation(renderInfo);
300 }
301 };
302
303
304 /** Set the callback to override the default Drawable::createCreateVertexArrayStateImplementation().*/
305 void setCreateVertexArrayStateCallback(CreateVertexArrayStateCallback* cb) { _createVertexArrayStateCallback = cb; }
306
307 /** Get the callback that overrides the default Drawable::createCreateVertexArrayStateImplementation().*/
308 CreateVertexArrayStateCallback* getCreateVertexArrayStateCallback() { return _createVertexArrayStateCallback.get(); }
309
310 /** Get the const callback that overrides the default Drawable::createCreateVertexArrayStateImplementation().*/
311 const CreateVertexArrayStateCallback* getCreateVertexArrayStateCallback() const { return _createVertexArrayStateCallback.get(); }
312
313
314 /** Create the VertexArrayState object used to track vertex array and vertex array object state. This method will be called automatically during rendering setup so users should not call this themselves.*/
315 inline VertexArrayState* createVertexArrayState(RenderInfo& renderInfo) const
316 {
317 if (_createVertexArrayStateCallback.valid()) return _createVertexArrayStateCallback->createVertexArrayStateImplementation(renderInfo, this);
318 else return createVertexArrayStateImplementation(renderInfo);
319 }
320
321 /** Implementation of Create the VertexArrayState object.*/
322 virtual VertexArrayState* createVertexArrayStateImplementation(RenderInfo& renderInfo) const;
323
324 void setVertexArrayStateList(VertexArrayStateList& vasl) { _vertexArrayStateList = vasl; }
325
326 VertexArrayStateList& getVertexArrayStateList() { return _vertexArrayStateList; }
327
328 const VertexArrayStateList& getVertexArrayStateList() const { return _vertexArrayStateList; }
329
330
331
332 /** Set whether to use a mutex to ensure ref() and unref() are thread safe.*/
333 virtual void setThreadSafeRefUnref(bool threadSafe);
334
335 /** Resize any per context GLObject buffers to specified size. */
336 virtual void resizeGLObjectBuffers(unsigned int maxSize);
337
338 /** If State is non-zero, this function releases OpenGL objects for
339 * the specified graphics context. Otherwise, releases OpenGL objects
340 * for all graphics contexts. */
341 virtual void releaseGLObjects(State* state=0) const;
342
343 // for backwards compatibility as local implementations are now found in osg namespace within the include/osg/Callback header
344 typedef DrawableUpdateCallback UpdateCallback;
345 typedef DrawableEventCallback EventCallback;
346 typedef DrawableCullCallback CullCallback;
347
348 /** Callback attached to an Drawable which allows the users to customize the drawing of an exist Drawable object.
349 * The draw callback is implement as a replacement to the Drawable's own drawImplementation() method, if the
350 * the user intends to decorate the existing draw code then simple call the drawable->drawImplementation() from
351 * with the callbacks drawImplementation() method. This allows the users to do both pre and post callbacks
352 * without fuss and can even disable the inner draw if required.*/
353 struct DrawCallback : public virtual osg::Object
354 {
355 DrawCallback() {}
356
357 DrawCallback(const DrawCallback& org,const CopyOp& copyop):
358 Object(org, copyop) {}
359
360 META_Object(osg,DrawCallback);
361
362 /** do customized draw code.*/
363 virtual void drawImplementation(osg::RenderInfo& /*renderInfo*/,const osg::Drawable* /*drawable*/) const {}
364 };
365
366 /** Set the DrawCallback which allows users to attach customize the drawing of existing Drawable object.*/
367 virtual void setDrawCallback(DrawCallback* dc) { _drawCallback=dc; dirtyGLObjects(); }
368
369 /** Get the non const DrawCallback.*/
370 DrawCallback* getDrawCallback() { return _drawCallback.get(); }
371
372 /** Get the const DrawCallback.*/
373 const DrawCallback* getDrawCallback() const { return _drawCallback.get(); }
374
375 /** drawImplementation(RenderInfo&) is a pure virtual method for the actual implementation of OpenGL drawing calls, such as vertex arrays and primitives, that
376 * must be implemented in concrete subclasses of the Drawable base class, examples include osg::Geometry and osg::ShapeDrawable.
377 * drawImplementation(RenderInfo&) is called from the draw(RenderInfo&) method, with the draw method handling management of OpenGL display lists,
378 * and drawImplementation(RenderInfo&) handling the actual drawing itself.
379 * renderInfo : The osg::RenderInfo object that encapsulates the current rendering information including the osg::State OpenGL state for the current graphics context. */
380 virtual void drawImplementation(RenderInfo& /*renderInfo*/) const {}
381
382
383 /** Return a OpenGL display list handle a newly generated or reused from display list cache. */
384 static GLuint generateDisplayList(unsigned int contextID, unsigned int sizeHint = 0);
385
386 /** Use deleteDisplayList instead of glDeleteList to allow
387 * OpenGL display list to be cached until they can be deleted
388 * by the OpenGL context in which they were created, specified
389 * by contextID.*/
390 static void deleteDisplayList(unsigned int contextID,GLuint globj, unsigned int sizeHint = 0);
391
392 /** Set the minimum number of display lists to retain in the deleted display list cache. */
393 static void setMinimumNumberOfDisplayListsToRetainInCache(unsigned int minimum);
394
395 /** Get the minimum number of display lists to retain in the deleted display list cache. */
396 static unsigned int getMinimumNumberOfDisplayListsToRetainInCache();
397
398
399
400 typedef unsigned int AttributeType;
401
402 enum AttributeTypes
403 {
404 VERTICES = 0,
405 WEIGHTS = 1,
406 NORMALS = 2,
407 COLORS = 3,
408 SECONDARY_COLORS = 4,
409 FOG_COORDS = 5,
410 ATTRIBUTE_6 = 6,
411 ATTRIBUTE_7 = 7,
412 TEXTURE_COORDS = 8,
413 TEXTURE_COORDS_0 = TEXTURE_COORDS,
414 TEXTURE_COORDS_1 = TEXTURE_COORDS_0+1,
415 TEXTURE_COORDS_2 = TEXTURE_COORDS_0+2,
416 TEXTURE_COORDS_3 = TEXTURE_COORDS_0+3,
417 TEXTURE_COORDS_4 = TEXTURE_COORDS_0+4,
418 TEXTURE_COORDS_5 = TEXTURE_COORDS_0+5,
419 TEXTURE_COORDS_6 = TEXTURE_COORDS_0+6,
420 TEXTURE_COORDS_7 = TEXTURE_COORDS_0+7
421 // only eight texture coord examples provided here, but underlying code can handle any no of texture units,
422 // simply co them as (TEXTURE_COORDS_0+unit).
423 };
424
425 class AttributeFunctor
426 {
427 public:
428 virtual ~AttributeFunctor() {}
429
430 virtual void apply(AttributeType,unsigned int,GLbyte*) {}
431 virtual void apply(AttributeType,unsigned int,GLshort*) {}
432 virtual void apply(AttributeType,unsigned int,GLint*) {}
433
434 virtual void apply(AttributeType,unsigned int,GLubyte*) {}
435 virtual void apply(AttributeType,unsigned int,GLushort*) {}
436 virtual void apply(AttributeType,unsigned int,GLuint*) {}
437
438 virtual void apply(AttributeType,unsigned int,float*) {}
439 virtual void apply(AttributeType,unsigned int,Vec2*) {}
440 virtual void apply(AttributeType,unsigned int,Vec3*) {}
441 virtual void apply(AttributeType,unsigned int,Vec4*) {}
442 virtual void apply(AttributeType,unsigned int,Vec4ub*) {}
443
444 virtual void apply(AttributeType,unsigned int,double*) {}
445 virtual void apply(AttributeType,unsigned int,Vec2d*) {}
446 virtual void apply(AttributeType,unsigned int,Vec3d*) {}
447 virtual void apply(AttributeType,unsigned int,Vec4d*) {}
448 };
449
450
451 /** Return true if the Drawable subclass supports accept(AttributeFunctor&).*/
452 virtual bool supports(const AttributeFunctor&) const { return false; }
453
454 /** accept an AttributeFunctor and call its methods to tell it about the internal attributes that this Drawable has.
455 * return true if functor handled by drawable,
456 * return false on failure of drawable to generate functor calls.*/
457 virtual void accept(AttributeFunctor&) {}
458
459
460 class ConstAttributeFunctor
461 {
462 public:
463
464 virtual ~ConstAttributeFunctor() {}
465
466 virtual void apply(AttributeType,unsigned int,const GLbyte*) {}
467 virtual void apply(AttributeType,unsigned int,const GLshort*) {}
468 virtual void apply(AttributeType,unsigned int,const GLint*) {}
469
470 virtual void apply(AttributeType,unsigned int,const GLubyte*) {}
471 virtual void apply(AttributeType,unsigned int,const GLushort*) {}
472 virtual void apply(AttributeType,unsigned int,const GLuint*) {}
473
474 virtual void apply(AttributeType,unsigned int,const float*) {}
475 virtual void apply(AttributeType,unsigned int,const Vec2*) {}
476 virtual void apply(AttributeType,unsigned int,const Vec3*) {}
477 virtual void apply(AttributeType,unsigned int,const Vec4*) {}
478 virtual void apply(AttributeType,unsigned int,const Vec4ub*) {}
479
480 virtual void apply(AttributeType,unsigned int,const double*) {}
481 virtual void apply(AttributeType,unsigned int,const Vec2d*) {}
482 virtual void apply(AttributeType,unsigned int,const Vec3d*) {}
483 virtual void apply(AttributeType,unsigned int,const Vec4d*) {}
484 };
485
486 /** Return true if the Drawable subclass supports accept(ConstAttributeFunctor&).*/
487 virtual bool supports(const ConstAttributeFunctor&) const { return false; }
488
489 /** Accept an AttributeFunctor and call its methods to tell it about the internal attributes that this Drawable has.
490 * return true if functor handled by drawable,
491 * return false on failure of drawable to generate functor calls.*/
492 virtual void accept(ConstAttributeFunctor&) const {}
493
494
495
496 /** Return true if the Drawable subclass supports accept(PrimitiveFunctor&).*/
497 virtual bool supports(const PrimitiveFunctor&) const { return false; }
498
499 /** Accept a PrimitiveFunctor and call its methods to tell it about the internal primitives that this Drawable has.
500 * return true if functor handled by drawable, return false on failure of drawable to generate functor calls.
501 * Note, PrimitiveFunctor only provides const access of the primitives, as primitives may be procedurally generated
502 * so one cannot modify it.*/
503 virtual void accept(PrimitiveFunctor&) const {}
504
505 /** Return true if the Drawable subclass supports accept(PrimitiveIndexFunctor&).*/
506 virtual bool supports(const PrimitiveIndexFunctor&) const { return false; }
507
508 /** Accept a PrimitiveIndexFunctor and call its methods to tell it about the internal primitives that this Drawable has.
509 * return true if functor handled by drawable, return false on failure of drawable to generate functor calls.
510 * Note, PrimitiveIndexFunctor only provide const access of the primitives, as primitives may be procedurally generated
511 * so one cannot modify it.*/
512 virtual void accept(PrimitiveIndexFunctor&) const {}
513
514 protected:
515
516 Drawable& operator = (const Drawable&) { return *this;}
517
518 virtual ~Drawable();
519
520 /** set the bounding box .*/
521 void setBound(const BoundingBox& bb) const;
522
523 friend class Node;
524 friend class Geode;
525 friend class StateSet;
526
527 BoundingBox _initialBoundingBox;
528 ref_ptr<ComputeBoundingBoxCallback> _computeBoundingBoxCallback;
529 mutable BoundingBox _boundingBox;
530
531 ref_ptr<Shape> _shape;
532
533 bool _supportsDisplayList;
534 bool _useDisplayList;
535 bool _supportsVertexBufferObjects;
536 bool _useVertexBufferObjects;
537 bool _useVertexArrayObject;
538
539 typedef osg::buffered_value<GLuint> GLObjectList;
540 mutable GLObjectList _globjList;
541
542 mutable VertexArrayStateList _vertexArrayStateList;
543
544 ref_ptr<DrawCallback> _drawCallback;
545 ref_ptr<CreateVertexArrayStateCallback> _createVertexArrayStateCallback;
546};
547
548#ifdef INLINE_DRAWABLE_DRAW
549inline void Drawable::draw(RenderInfo& renderInfo) const
550{
551 State& state = *renderInfo.getState();
552 bool useVertexArrayObject = state.useVertexArrayObject(_useVertexArrayObject);
553 if (useVertexArrayObject)
554 {
555 unsigned int contextID = renderInfo.getContextID();
556
557 VertexArrayState* vas = _vertexArrayStateList[contextID].get();
558 if (!vas)
559 {
560 _vertexArrayStateList[contextID] = vas = createVertexArrayState(renderInfo);
561 }
562 else
563 {
564 // vas->setRequiresSetArrays(getDataVariance()==osg::Object::DYNAMIC);
565 }
566
567 State::SetCurrentVertexArrayStateProxy setVASProxy(state, vas);
568
569 state.bindVertexArrayObject(vas);
570
571 drawInner(renderInfo);
572
573 vas->setRequiresSetArrays(getDataVariance()==osg::Object::DYNAMIC);
574
575 return;
576 }
577
578 // TODO, add check against whether VAO is active and supported
579 if (state.getCurrentVertexArrayState())
580 {
581 //OSG_NOTICE<<"state.getCurrentVertexArrayState()->getVertexArrayObject()="<< state.getCurrentVertexArrayState()->getVertexArrayObject()<<std::endl;
582 state.bindVertexArrayObject(state.getCurrentVertexArrayState());
583 }
584
585
586#ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
587 if (!state.useVertexBufferObject(_supportsVertexBufferObjects && _useVertexBufferObjects) && _useDisplayList)
588 {
589 // get the contextID (user defined ID of 0 upwards) for the
590 // current OpenGL context.
591 unsigned int contextID = renderInfo.getContextID();
592
593 // get the globj for the current contextID.
594 GLuint& globj = _globjList[contextID];
595
596 if( globj == 0 )
597 {
598 // compile the display list
599 globj = generateDisplayList(contextID, getGLObjectSizeHint());
600 glNewList( globj, GL_COMPILE );
601
602 drawInner(renderInfo);
603
604 glEndList();
605 }
606
607 // call the display list
608 glCallList( globj);
609 }
610 else
611#endif
612 {
613 // if state.previousVertexArrayState() is different than currentVertexArrayState bind current
614
615 // OSG_NOTICE<<"Fallback drawInner()........................"<<std::endl;
616
617 drawInner(renderInfo);
618 }
619}
620#endif
621
622class AttributeFunctorArrayVisitor : public ArrayVisitor
623{
624 public:
625
626 AttributeFunctorArrayVisitor(Drawable::AttributeFunctor& af):
627 _af(af),
628 _type(0) {}
629
630 virtual ~AttributeFunctorArrayVisitor() {}
631
632 virtual void apply(ByteArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
633 virtual void apply(ShortArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
634 virtual void apply(IntArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
635 virtual void apply(UByteArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
636 virtual void apply(UShortArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
637 virtual void apply(UIntArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
638 virtual void apply(Vec4ubArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
639 virtual void apply(FloatArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
640 virtual void apply(Vec2Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
641 virtual void apply(Vec3Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
642 virtual void apply(Vec4Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
643 virtual void apply(DoubleArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
644 virtual void apply(Vec2dArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
645 virtual void apply(Vec3dArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
646 virtual void apply(Vec4dArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
647
648
649 inline void applyArray(Drawable::AttributeType type,Array* array)
650 {
651 if (array)
652 {
653 _type = type;
654 array->accept(*this);
655 }
656 }
657
658 protected:
659
660 AttributeFunctorArrayVisitor& operator = (const AttributeFunctorArrayVisitor&) { return *this; }
661 Drawable::AttributeFunctor& _af;
662 Drawable::AttributeType _type;
663};
664
665class ConstAttributeFunctorArrayVisitor : public ConstArrayVisitor
666{
667 public:
668
669 ConstAttributeFunctorArrayVisitor(Drawable::ConstAttributeFunctor& af):
670 _af(af),
671 _type(0) {}
672
673 virtual ~ConstAttributeFunctorArrayVisitor() {}
674
675 virtual void apply(const ByteArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
676 virtual void apply(const ShortArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
677 virtual void apply(const IntArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
678 virtual void apply(const UByteArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
679 virtual void apply(const UShortArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
680 virtual void apply(const UIntArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
681 virtual void apply(const Vec4ubArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
682 virtual void apply(const FloatArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
683 virtual void apply(const Vec2Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
684 virtual void apply(const Vec3Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
685 virtual void apply(const Vec4Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
686 virtual void apply(const DoubleArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
687 virtual void apply(const Vec2dArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
688 virtual void apply(const Vec3dArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
689 virtual void apply(const Vec4dArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); }
690
691
692 inline void applyArray(Drawable::AttributeType type,const Array* array)
693 {
694 if (array)
695 {
696 _type = type;
697 array->accept(*this);
698 }
699 }
700
701protected:
702
703 ConstAttributeFunctorArrayVisitor& operator = (const ConstAttributeFunctorArrayVisitor&) { return *this; }
704
705 Drawable::ConstAttributeFunctor& _af;
706 Drawable::AttributeType _type;
707};
708
709}
710
711#endif