1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
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.
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.
17#include <osg/BoundingBox>
19#include <osg/BufferObject>
20#include <osg/PrimitiveSet>
21#include <osg/RenderInfo>
25#ifndef GL_NV_occlusion_query
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
36#ifndef GL_ARB_occlusion_query
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
47#ifndef GL_TIME_ELAPSED
48 #define GL_TIME_ELAPSED 0x88BF
49 #define GL_TIMESTAMP 0x8E28
52#ifndef GL_QUERY_RESULT
53 #define GL_QUERY_RESULT 0x8866
54 #define GL_QUERY_RESULT_AVAILABLE 0x8867
58#define INLINE_DRAWABLE_DRAW
69class ArrayDispatchers;
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.
88class OSG_EXPORT Drawable : public Node
94 /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
95 Drawable(const Drawable& drawable,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
97 META_Node(osg, Drawable);
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; }
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; }
107 /** Compute the DataVariance based on an assessment of callback etc.*/
108 virtual void computeDataVariance();
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;
115 /** Set the initial bounding volume to use when computing the overall bounding volume.*/
116 void setInitialBound(const osg::BoundingBox& bbox) { _initialBoundingBox = bbox; dirtyBound(); }
118 /** Set the initial bounding volume to use when computing the overall bounding volume.*/
119 const BoundingBox& getInitialBound() const { return _initialBoundingBox; }
121 inline const BoundingSphere& getBound() const
123 if(!_boundingSphereComputed) getBoundingBox();
124 return _boundingSphere;
127 /** Get BoundingBox of Drawable.
128 * If the BoundingBox is not up to date then its updated via an internal call to computeBond().
130 inline const BoundingBox& getBoundingBox() const
132 if(!_boundingSphereComputed)
134 _boundingBox = _initialBoundingBox;
136 if (_computeBoundingBoxCallback.valid())
137 _boundingBox.expandBy(_computeBoundingBoxCallback->computeBound(*this));
139 _boundingBox.expandBy(computeBoundingBox());
141 if(_boundingBox.valid()){
142 _boundingSphere.set(_boundingBox.center(), _boundingBox.radius());
144 _boundingSphere.init();
147 _boundingSphereComputed = true;
154 /** Compute the bounding sphere around Drawables's geometry.*/
155 virtual BoundingSphere computeBound() const;
157 /** Compute the bounding box around Drawables's geometry.*/
158 virtual BoundingBox computeBoundingBox() const;
160 /** Callback to allow users to override the default computation of bounding volume. */
161 struct ComputeBoundingBoxCallback : public osg::Object
163 ComputeBoundingBoxCallback() {}
165 ComputeBoundingBoxCallback(const ComputeBoundingBoxCallback& org,const CopyOp& copyop):
166 Object(org, copyop) {}
168 META_Object(osg,ComputeBoundingBoxCallback);
170 virtual BoundingBox computeBound(const osg::Drawable&) const { return BoundingBox(); }
173 /** Set the compute bound callback to override the default computeBound.*/
174 void setComputeBoundingBoxCallback(ComputeBoundingBoxCallback* callback) { _computeBoundingBoxCallback = callback; }
176 /** Get the compute bound callback.*/
177 ComputeBoundingBoxCallback* getComputeBoundingBoxCallback() { return _computeBoundingBoxCallback.get(); }
179 /** Get the const compute bound callback.*/
180 const ComputeBoundingBoxCallback* getComputeBoundingBoxCallback() const { return _computeBoundingBoxCallback.get(); }
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.
188 virtual void setShape(Shape* shape) { _shape = shape; }
190 template<class T> void setShape(const ref_ptr<T>& shape) { setShape(shape.get()); }
192 /** Get the Shape of the Drawable.*/
193 inline Shape* getShape() { return _shape.get(); }
195 /** Get the const Shape of the const Drawable.*/
196 inline const Shape* getShape() const { return _shape.get(); }
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
207 void setSupportsDisplayList(bool flag);
209 /** Get whether display lists are supported for this drawable instance.*/
210 inline bool getSupportsDisplayList() const { return _supportsDisplayList; }
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);
218 /** Return whether OpenGL display lists are being used for rendering.*/
219 inline bool getUseDisplayList() const { return _useDisplayList; }
221 /** Return OpenGL display list for specified contextID. */
222 inline GLuint& getDisplayList(unsigned int contextID) const { return _globjList[contextID]; }
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);
228 /** Return whether OpenGL vertex buffer objects should be used when supported by OpenGL driver.*/
229 inline bool getUseVertexBufferObjects() const { return _useVertexBufferObjects; }
232 /** Set whether to use a local VertexArrayObject for this Drawable.*/
233 void setUseVertexArrayObject(bool flag);
235 /** Return whether to use a local VertexArrayObject for this Drawable.*/
236 bool getUseVertexArrayObject() const { return _useVertexArrayObject; }
238#ifdef OSG_USE_DEPRECATED_API
239 /** Deprecated, use dirtyGLObjects() instead. */
240 inline void dirtyDisplayList()
246 /** Force a recompile on next draw() of any OpenGL objects associated with this geoset.*/
247 virtual void dirtyGLObjects();
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; }
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.
265#ifdef INLINE_DRAWABLE_DRAW
266 inline void draw(RenderInfo& renderInfo) const;
268 void draw(RenderInfo& renderInfo) const;
271 inline void drawInner(RenderInfo& renderInfo) const
273 if (_drawCallback.valid())
274 _drawCallback->drawImplementation(renderInfo,this);
276 drawImplementation(renderInfo);
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.
283 virtual void compileGLObjects(RenderInfo& renderInfo) const;
286 /** Callback class for overriding the default Drawable::createCreateVertexArrayStateImplementation().*/
287 struct CreateVertexArrayStateCallback : public virtual osg::Object
289 CreateVertexArrayStateCallback() {}
291 CreateVertexArrayStateCallback(const CreateVertexArrayStateCallback& rhs,const CopyOp& copyop):
292 Object(rhs, copyop) {}
294 META_Object(osg, CreateVertexArrayStateCallback);
296 /** do customized createVertexArrayState .*/
297 virtual osg::VertexArrayState* createVertexArrayStateImplementation(osg::RenderInfo& renderInfo, const osg::Drawable* drawable) const
299 return drawable->createVertexArrayStateImplementation(renderInfo);
304 /** Set the callback to override the default Drawable::createCreateVertexArrayStateImplementation().*/
305 void setCreateVertexArrayStateCallback(CreateVertexArrayStateCallback* cb) { _createVertexArrayStateCallback = cb; }
307 /** Get the callback that overrides the default Drawable::createCreateVertexArrayStateImplementation().*/
308 CreateVertexArrayStateCallback* getCreateVertexArrayStateCallback() { return _createVertexArrayStateCallback.get(); }
310 /** Get the const callback that overrides the default Drawable::createCreateVertexArrayStateImplementation().*/
311 const CreateVertexArrayStateCallback* getCreateVertexArrayStateCallback() const { return _createVertexArrayStateCallback.get(); }
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
317 if (_createVertexArrayStateCallback.valid()) return _createVertexArrayStateCallback->createVertexArrayStateImplementation(renderInfo, this);
318 else return createVertexArrayStateImplementation(renderInfo);
321 /** Implementation of Create the VertexArrayState object.*/
322 virtual VertexArrayState* createVertexArrayStateImplementation(RenderInfo& renderInfo) const;
324 void setVertexArrayStateList(VertexArrayStateList& vasl) { _vertexArrayStateList = vasl; }
326 VertexArrayStateList& getVertexArrayStateList() { return _vertexArrayStateList; }
328 const VertexArrayStateList& getVertexArrayStateList() const { return _vertexArrayStateList; }
332 /** Set whether to use a mutex to ensure ref() and unref() are thread safe.*/
333 virtual void setThreadSafeRefUnref(bool threadSafe);
335 /** Resize any per context GLObject buffers to specified size. */
336 virtual void resizeGLObjectBuffers(unsigned int maxSize);
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;
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;
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
357 DrawCallback(const DrawCallback& org,const CopyOp& copyop):
358 Object(org, copyop) {}
360 META_Object(osg,DrawCallback);
362 /** do customized draw code.*/
363 virtual void drawImplementation(osg::RenderInfo& /*renderInfo*/,const osg::Drawable* /*drawable*/) const {}
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(); }
369 /** Get the non const DrawCallback.*/
370 DrawCallback* getDrawCallback() { return _drawCallback.get(); }
372 /** Get the const DrawCallback.*/
373 const DrawCallback* getDrawCallback() const { return _drawCallback.get(); }
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 {}
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);
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
390 static void deleteDisplayList(unsigned int contextID,GLuint globj, unsigned int sizeHint = 0);
392 /** Set the minimum number of display lists to retain in the deleted display list cache. */
393 static void setMinimumNumberOfDisplayListsToRetainInCache(unsigned int minimum);
395 /** Get the minimum number of display lists to retain in the deleted display list cache. */
396 static unsigned int getMinimumNumberOfDisplayListsToRetainInCache();
400 typedef unsigned int AttributeType;
408 SECONDARY_COLORS = 4,
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).
425 class AttributeFunctor
428 virtual ~AttributeFunctor() {}
430 virtual void apply(AttributeType,unsigned int,GLbyte*) {}
431 virtual void apply(AttributeType,unsigned int,GLshort*) {}
432 virtual void apply(AttributeType,unsigned int,GLint*) {}
434 virtual void apply(AttributeType,unsigned int,GLubyte*) {}
435 virtual void apply(AttributeType,unsigned int,GLushort*) {}
436 virtual void apply(AttributeType,unsigned int,GLuint*) {}
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*) {}
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*) {}
451 /** Return true if the Drawable subclass supports accept(AttributeFunctor&).*/
452 virtual bool supports(const AttributeFunctor&) const { return false; }
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&) {}
460 class ConstAttributeFunctor
464 virtual ~ConstAttributeFunctor() {}
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*) {}
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*) {}
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*) {}
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*) {}
486 /** Return true if the Drawable subclass supports accept(ConstAttributeFunctor&).*/
487 virtual bool supports(const ConstAttributeFunctor&) const { return false; }
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 {}
496 /** Return true if the Drawable subclass supports accept(PrimitiveFunctor&).*/
497 virtual bool supports(const PrimitiveFunctor&) const { return false; }
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 {}
505 /** Return true if the Drawable subclass supports accept(PrimitiveIndexFunctor&).*/
506 virtual bool supports(const PrimitiveIndexFunctor&) const { return false; }
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 {}
516 Drawable& operator = (const Drawable&) { return *this;}
520 /** set the bounding box .*/
521 void setBound(const BoundingBox& bb) const;
525 friend class StateSet;
527 BoundingBox _initialBoundingBox;
528 ref_ptr<ComputeBoundingBoxCallback> _computeBoundingBoxCallback;
529 mutable BoundingBox _boundingBox;
531 ref_ptr<Shape> _shape;
533 bool _supportsDisplayList;
534 bool _useDisplayList;
535 bool _supportsVertexBufferObjects;
536 bool _useVertexBufferObjects;
537 bool _useVertexArrayObject;
539 typedef osg::buffered_value<GLuint> GLObjectList;
540 mutable GLObjectList _globjList;
542 mutable VertexArrayStateList _vertexArrayStateList;
544 ref_ptr<DrawCallback> _drawCallback;
545 ref_ptr<CreateVertexArrayStateCallback> _createVertexArrayStateCallback;
548#ifdef INLINE_DRAWABLE_DRAW
549inline void Drawable::draw(RenderInfo& renderInfo) const
551 State& state = *renderInfo.getState();
552 bool useVertexArrayObject = state.useVertexArrayObject(_useVertexArrayObject);
553 if (useVertexArrayObject)
555 unsigned int contextID = renderInfo.getContextID();
557 VertexArrayState* vas = _vertexArrayStateList[contextID].get();
560 _vertexArrayStateList[contextID] = vas = createVertexArrayState(renderInfo);
564 // vas->setRequiresSetArrays(getDataVariance()==osg::Object::DYNAMIC);
567 State::SetCurrentVertexArrayStateProxy setVASProxy(state, vas);
569 state.bindVertexArrayObject(vas);
571 drawInner(renderInfo);
573 vas->setRequiresSetArrays(getDataVariance()==osg::Object::DYNAMIC);
578 // TODO, add check against whether VAO is active and supported
579 if (state.getCurrentVertexArrayState())
581 //OSG_NOTICE<<"state.getCurrentVertexArrayState()->getVertexArrayObject()="<< state.getCurrentVertexArrayState()->getVertexArrayObject()<<std::endl;
582 state.bindVertexArrayObject(state.getCurrentVertexArrayState());
586#ifdef OSG_GL_DISPLAYLISTS_AVAILABLE
587 if (!state.useVertexBufferObject(_supportsVertexBufferObjects && _useVertexBufferObjects) && _useDisplayList)
589 // get the contextID (user defined ID of 0 upwards) for the
590 // current OpenGL context.
591 unsigned int contextID = renderInfo.getContextID();
593 // get the globj for the current contextID.
594 GLuint& globj = _globjList[contextID];
598 // compile the display list
599 globj = generateDisplayList(contextID, getGLObjectSizeHint());
600 glNewList( globj, GL_COMPILE );
602 drawInner(renderInfo);
607 // call the display list
613 // if state.previousVertexArrayState() is different than currentVertexArrayState bind current
615 // OSG_NOTICE<<"Fallback drawInner()........................"<<std::endl;
617 drawInner(renderInfo);
622class AttributeFunctorArrayVisitor : public ArrayVisitor
626 AttributeFunctorArrayVisitor(Drawable::AttributeFunctor& af):
630 virtual ~AttributeFunctorArrayVisitor() {}
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())); }
649 inline void applyArray(Drawable::AttributeType type,Array* array)
654 array->accept(*this);
660 AttributeFunctorArrayVisitor& operator = (const AttributeFunctorArrayVisitor&) { return *this; }
661 Drawable::AttributeFunctor& _af;
662 Drawable::AttributeType _type;
665class ConstAttributeFunctorArrayVisitor : public ConstArrayVisitor
669 ConstAttributeFunctorArrayVisitor(Drawable::ConstAttributeFunctor& af):
673 virtual ~ConstAttributeFunctorArrayVisitor() {}
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())); }
692 inline void applyArray(Drawable::AttributeType type,const Array* array)
697 array->accept(*this);
703 ConstAttributeFunctorArrayVisitor& operator = (const ConstAttributeFunctorArrayVisitor&) { return *this; }
705 Drawable::ConstAttributeFunctor& _af;
706 Drawable::AttributeType _type;