mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-31 08:26:42 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			472 lines
		
	
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			472 lines
		
	
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // clang-format off
 | |
| /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 | |
|  *
 | |
|  * This library is open source and may be redistributed and/or modified under
 | |
|  * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 | |
|  * (at your option) any later version.  The full license is in LICENSE file
 | |
|  * included with this distribution, and on the openscenegraph.org website.
 | |
|  *
 | |
|  * This library is distributed in the hope that it will be useful,
 | |
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|  * OpenSceneGraph Public License for more details.
 | |
| */
 | |
| 
 | |
| /* Modified for OpenMW */
 | |
| 
 | |
| #ifndef OPENMW_OSGUTIL_OPTIMIZER
 | |
| #define OPENMW_OSGUTIL_OPTIMIZER
 | |
| 
 | |
| #include <osg/NodeVisitor>
 | |
| #include <osg/Matrix>
 | |
| #include <osg/Geometry>
 | |
| #include <osg/Transform>
 | |
| #include <osg/Texture2D>
 | |
| 
 | |
| //#include <osgUtil/Export>
 | |
| 
 | |
| #include <set>
 | |
| #include <mutex>
 | |
| 
 | |
| namespace osgDB
 | |
| {
 | |
|     class SharedStateManager;
 | |
| }
 | |
| 
 | |
| //namespace osgUtil {
 | |
| namespace SceneUtil {
 | |
| 
 | |
| // forward declare
 | |
| class Optimizer;
 | |
| 
 | |
| /** Helper base class for implementing Optimizer techniques.*/
 | |
| class BaseOptimizerVisitor : public osg::NodeVisitor
 | |
| {
 | |
|     public:
 | |
| 
 | |
|         BaseOptimizerVisitor(Optimizer* optimizer, unsigned int operation):
 | |
|             osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
 | |
|             _optimizer(optimizer),
 | |
|             _operationType(operation)
 | |
|         {
 | |
|             setNodeMaskOverride(0xffffffff);
 | |
|         }
 | |
| 
 | |
|         inline bool isOperationPermissibleForObject(const osg::StateSet* object) const;
 | |
|         inline bool isOperationPermissibleForObject(const osg::StateAttribute* object) const;
 | |
|         inline bool isOperationPermissibleForObject(const osg::Drawable* object) const;
 | |
|         inline bool isOperationPermissibleForObject(const osg::Node* object) const;
 | |
| 
 | |
|     protected:
 | |
| 
 | |
|         Optimizer*      _optimizer;
 | |
|         unsigned int _operationType;
 | |
| };
 | |
| 
 | |
| /** Traverses scene graph to improve efficiency. See OptimizationOptions.
 | |
|   * For example of usage see examples/osgimpostor or osgviewer.
 | |
|   */
 | |
| 
 | |
| class Optimizer
 | |
| {
 | |
| 
 | |
|     public:
 | |
| 
 | |
|         Optimizer() : _mergeAlphaBlending(false), _sharedStateManager(nullptr), _sharedStateMutex(nullptr) {}
 | |
|         virtual ~Optimizer() {}
 | |
| 
 | |
|         enum OptimizationOptions
 | |
|         {
 | |
|             FLATTEN_STATIC_TRANSFORMS = (1 << 0),
 | |
|             REMOVE_REDUNDANT_NODES =    (1 << 1),
 | |
|             REMOVE_LOADED_PROXY_NODES = (1 << 2),
 | |
|             COMBINE_ADJACENT_LODS =     (1 << 3),
 | |
|             SHARE_DUPLICATE_STATE =     (1 << 4),
 | |
|             MERGE_GEOMETRY =            (1 << 5),
 | |
|             CHECK_GEOMETRY =            (1 << 6), // deprecated, currently no-op
 | |
|             MAKE_FAST_GEOMETRY =        (1 << 7),
 | |
|             SPATIALIZE_GROUPS =         (1 << 8),
 | |
|             COPY_SHARED_NODES =         (1 << 9),
 | |
|             TRISTRIP_GEOMETRY =         (1 << 10),
 | |
|             TESSELLATE_GEOMETRY =       (1 << 11),
 | |
|             OPTIMIZE_TEXTURE_SETTINGS = (1 << 12),
 | |
|             MERGE_GEODES =              (1 << 13),
 | |
|             FLATTEN_BILLBOARDS =        (1 << 14),
 | |
|             TEXTURE_ATLAS_BUILDER =     (1 << 15),
 | |
|             STATIC_OBJECT_DETECTION =   (1 << 16),
 | |
|             FLATTEN_STATIC_TRANSFORMS_DUPLICATING_SHARED_SUBGRAPHS = (1 << 17),
 | |
|             INDEX_MESH =                (1 << 18),
 | |
|             VERTEX_POSTTRANSFORM =      (1 << 19),
 | |
|             VERTEX_PRETRANSFORM =       (1 << 20),
 | |
|             DEFAULT_OPTIMIZATIONS = FLATTEN_STATIC_TRANSFORMS |
 | |
|                                 REMOVE_REDUNDANT_NODES |
 | |
|                                 REMOVE_LOADED_PROXY_NODES |
 | |
|                                 COMBINE_ADJACENT_LODS |
 | |
|                                 SHARE_DUPLICATE_STATE |
 | |
|                                 MERGE_GEOMETRY |
 | |
|                                 MAKE_FAST_GEOMETRY |
 | |
|                                 CHECK_GEOMETRY |
 | |
|                                 OPTIMIZE_TEXTURE_SETTINGS |
 | |
|                                 STATIC_OBJECT_DETECTION,
 | |
|             ALL_OPTIMIZATIONS = FLATTEN_STATIC_TRANSFORMS_DUPLICATING_SHARED_SUBGRAPHS |
 | |
|                                 REMOVE_REDUNDANT_NODES |
 | |
|                                 REMOVE_LOADED_PROXY_NODES |
 | |
|                                 COMBINE_ADJACENT_LODS |
 | |
|                                 SHARE_DUPLICATE_STATE |
 | |
|                                 MERGE_GEODES |
 | |
|                                 MERGE_GEOMETRY |
 | |
|                                 MAKE_FAST_GEOMETRY |
 | |
|                                 CHECK_GEOMETRY |
 | |
|                                 SPATIALIZE_GROUPS |
 | |
|                                 COPY_SHARED_NODES |
 | |
|                                 TRISTRIP_GEOMETRY |
 | |
|                                 OPTIMIZE_TEXTURE_SETTINGS |
 | |
|                                 TEXTURE_ATLAS_BUILDER |
 | |
|                                 STATIC_OBJECT_DETECTION
 | |
|         };
 | |
| 
 | |
|         void setMergeAlphaBlending(bool merge) { _mergeAlphaBlending = merge; }
 | |
|         void setViewPoint(const osg::Vec3f& viewPoint) { _viewPoint = viewPoint; }
 | |
| 
 | |
|         void setSharedStateManager(osgDB::SharedStateManager* sharedStateManager, std::mutex* sharedStateMutex) { _sharedStateMutex = sharedStateMutex; _sharedStateManager = sharedStateManager; }
 | |
| 
 | |
|         /** Reset internal data to initial state - the getPermissibleOptionsMap is cleared.*/
 | |
|         void reset();
 | |
| 
 | |
|         /** Traverse the node and its subgraph with a series of optimization
 | |
|           * visitors, specified by the OptimizationOptions.*/
 | |
|         virtual void optimize(osg::Node* node, unsigned int options);
 | |
| 
 | |
| 
 | |
|         /** Callback for customizing what operations are permitted on objects in the scene graph.*/
 | |
|         struct IsOperationPermissibleForObjectCallback : public osg::Referenced
 | |
|         {
 | |
|             virtual bool isOperationPermissibleForObjectImplementation(const Optimizer* optimizer, const osg::StateSet* stateset,unsigned int option) const
 | |
|             {
 | |
|                 return optimizer->isOperationPermissibleForObjectImplementation(stateset,option);
 | |
|             }
 | |
| 
 | |
|             virtual bool isOperationPermissibleForObjectImplementation(const Optimizer* optimizer, const osg::StateAttribute* attribute,unsigned int option) const
 | |
|             {
 | |
|                 return optimizer->isOperationPermissibleForObjectImplementation(attribute,option);
 | |
|             }
 | |
| 
 | |
|             virtual bool isOperationPermissibleForObjectImplementation(const Optimizer* optimizer, const osg::Drawable* drawable,unsigned int option) const
 | |
|             {
 | |
|                 return optimizer->isOperationPermissibleForObjectImplementation(drawable,option);
 | |
|             }
 | |
| 
 | |
|             virtual bool isOperationPermissibleForObjectImplementation(const Optimizer* optimizer, const osg::Node* node,unsigned int option) const
 | |
|             {
 | |
|                 return optimizer->isOperationPermissibleForObjectImplementation(node,option);
 | |
|             }
 | |
| 
 | |
|         };
 | |
| 
 | |
|         /** Set the callback for customizing what operations are permitted on objects in the scene graph.*/
 | |
|         void setIsOperationPermissibleForObjectCallback(IsOperationPermissibleForObjectCallback* callback) { _isOperationPermissibleForObjectCallback=callback; }
 | |
| 
 | |
|         /** Get the callback for customizing what operations are permitted on objects in the scene graph.*/
 | |
|         IsOperationPermissibleForObjectCallback* getIsOperationPermissibleForObjectCallback() { return _isOperationPermissibleForObjectCallback.get(); }
 | |
| 
 | |
|         /** Get the callback for customizing what operations are permitted on objects in the scene graph.*/
 | |
|         const IsOperationPermissibleForObjectCallback* getIsOperationPermissibleForObjectCallback() const { return _isOperationPermissibleForObjectCallback.get(); }
 | |
| 
 | |
| 
 | |
|         inline void setPermissibleOptimizationsForObject(const osg::Object* object, unsigned int options)
 | |
|         {
 | |
|             _permissibleOptimizationsMap[object] = options;
 | |
|         }
 | |
| 
 | |
|         inline unsigned int getPermissibleOptimizationsForObject(const osg::Object* object) const
 | |
|         {
 | |
|             PermissibleOptimizationsMap::const_iterator itr = _permissibleOptimizationsMap.find(object);
 | |
|             if (itr!=_permissibleOptimizationsMap.end()) return itr->second;
 | |
|             else return 0xffffffff;
 | |
|         }
 | |
| 
 | |
| 
 | |
|         inline bool isOperationPermissibleForObject(const osg::StateSet* object, unsigned int option) const
 | |
|         {
 | |
|             if (_isOperationPermissibleForObjectCallback.valid())
 | |
|                 return _isOperationPermissibleForObjectCallback->isOperationPermissibleForObjectImplementation(this,object,option);
 | |
|             else
 | |
|                 return isOperationPermissibleForObjectImplementation(object,option);
 | |
|         }
 | |
| 
 | |
|         inline bool isOperationPermissibleForObject(const osg::StateAttribute* object, unsigned int option) const
 | |
|         {
 | |
|             if (_isOperationPermissibleForObjectCallback.valid())
 | |
|                 return _isOperationPermissibleForObjectCallback->isOperationPermissibleForObjectImplementation(this,object,option);
 | |
|             else
 | |
|                 return isOperationPermissibleForObjectImplementation(object,option);
 | |
|         }
 | |
| 
 | |
|         inline bool isOperationPermissibleForObject(const osg::Drawable* object, unsigned int option) const
 | |
|         {
 | |
|             if (_isOperationPermissibleForObjectCallback.valid())
 | |
|                 return _isOperationPermissibleForObjectCallback->isOperationPermissibleForObjectImplementation(this,object,option);
 | |
|             else
 | |
|                 return isOperationPermissibleForObjectImplementation(object,option);
 | |
|         }
 | |
| 
 | |
|         inline bool isOperationPermissibleForObject(const osg::Node* object, unsigned int option) const
 | |
|         {
 | |
|             if (_isOperationPermissibleForObjectCallback.valid())
 | |
|                 return _isOperationPermissibleForObjectCallback->isOperationPermissibleForObjectImplementation(this,object,option);
 | |
|             else
 | |
|                 return isOperationPermissibleForObjectImplementation(object,option);
 | |
|         }
 | |
| 
 | |
|         bool isOperationPermissibleForObjectImplementation(const osg::StateSet* stateset, unsigned int option) const
 | |
|         {
 | |
|             return (option & getPermissibleOptimizationsForObject(stateset))!=0;
 | |
|         }
 | |
| 
 | |
|         bool isOperationPermissibleForObjectImplementation(const osg::StateAttribute* attribute, unsigned int option) const
 | |
|         {
 | |
|             return (option & getPermissibleOptimizationsForObject(attribute))!=0;
 | |
|         }
 | |
| 
 | |
|         bool isOperationPermissibleForObjectImplementation(const osg::Drawable* drawable, unsigned int option) const
 | |
|         {
 | |
|             if (option & (REMOVE_REDUNDANT_NODES|MERGE_GEOMETRY))
 | |
|             {
 | |
|                 if (drawable->getUserData()) return false;
 | |
|                 if (drawable->getUpdateCallback()) return false;
 | |
|                 if (drawable->getEventCallback()) return false;
 | |
|                 if (drawable->getCullCallback()) return false;
 | |
|             }
 | |
|             return (option & getPermissibleOptimizationsForObject(drawable))!=0;
 | |
|         }
 | |
| 
 | |
|         bool isOperationPermissibleForObjectImplementation(const osg::Node* node, unsigned int option) const
 | |
|         {
 | |
|             if (option & (REMOVE_REDUNDANT_NODES|COMBINE_ADJACENT_LODS|FLATTEN_STATIC_TRANSFORMS))
 | |
|             {
 | |
|                 if (node->getUserData()) return false;
 | |
|                 if (node->getUpdateCallback()) return false;
 | |
|                 if (node->getEventCallback()) return false;
 | |
|                 if (node->getCullCallback()) return false;
 | |
|                 if (node->getNumDescriptions()>0) return false;
 | |
|                 if (node->getStateSet()) return false;
 | |
|                 if (node->getNodeMask()!=0xffffffff) return false;
 | |
|                 // if (!node->getName().empty()) return false;
 | |
|             }
 | |
| 
 | |
|             return (option & getPermissibleOptimizationsForObject(node))!=0;
 | |
|         }
 | |
| 
 | |
|     protected:
 | |
| 
 | |
|         osg::ref_ptr<IsOperationPermissibleForObjectCallback> _isOperationPermissibleForObjectCallback;
 | |
| 
 | |
|         typedef std::map<const osg::Object*,unsigned int> PermissibleOptimizationsMap;
 | |
|         PermissibleOptimizationsMap _permissibleOptimizationsMap;
 | |
| 
 | |
|         osg::Vec3f _viewPoint;
 | |
|         bool _mergeAlphaBlending;
 | |
| 
 | |
|         osgDB::SharedStateManager* _sharedStateManager;
 | |
|         mutable std::mutex* _sharedStateMutex;
 | |
| 
 | |
|     public:
 | |
| 
 | |
|         /** Flatten Static Transform nodes by applying their transform to the
 | |
|           * geometry on the leaves of the scene graph, then removing the
 | |
|           * now redundant transforms.  Static transformed subgraphs that have multiple
 | |
|           * parental paths above them are not flattened, if you require this then
 | |
|           * the subgraphs have to be duplicated - for this use the
 | |
|           * FlattenStaticTransformsDuplicatingSharedSubgraphsVisitor. */
 | |
|         class FlattenStaticTransformsVisitor : public BaseOptimizerVisitor
 | |
|         {
 | |
|             public:
 | |
| 
 | |
|                 FlattenStaticTransformsVisitor(Optimizer* optimizer=0):
 | |
|                     BaseOptimizerVisitor(optimizer, FLATTEN_STATIC_TRANSFORMS) {}
 | |
| 
 | |
|                 void apply(osg::Node& node) override;
 | |
|                 void apply(osg::Geometry& geometry) override;
 | |
|                 void apply(osg::Drawable& drawable) override;
 | |
|                 void apply(osg::Billboard& billboard) override;
 | |
|                 void apply(osg::Transform& transform) override final;
 | |
|                 void apply(osg::MatrixTransform& transform) override;
 | |
| 
 | |
|                 bool removeTransforms(osg::Node* nodeWeCannotRemove);
 | |
| 
 | |
|             protected:
 | |
| 
 | |
|                 typedef std::vector<osg::Transform*>                TransformStack;
 | |
|                 typedef std::set<osg::Drawable*>                    DrawableSet;
 | |
|                 typedef std::set<osg::Billboard*>                   BillboardSet;
 | |
|                 typedef std::set<osg::Node* >                       NodeSet;
 | |
|                 typedef std::set<osg::Transform*>                   TransformSet;
 | |
| 
 | |
|                 TransformStack  _transformStack;
 | |
|                 NodeSet         _excludedNodeSet;
 | |
|                 DrawableSet     _drawableSet;
 | |
|                 BillboardSet    _billboardSet;
 | |
|                 TransformSet    _transformSet;
 | |
|         };
 | |
| 
 | |
| 
 | |
|         /** Combine Static Transform nodes that sit above one another.*/
 | |
|         class CombineStaticTransformsVisitor : public BaseOptimizerVisitor
 | |
|         {
 | |
|             public:
 | |
| 
 | |
|                 CombineStaticTransformsVisitor(Optimizer* optimizer=0):
 | |
|                     BaseOptimizerVisitor(optimizer, FLATTEN_STATIC_TRANSFORMS) {}
 | |
| 
 | |
|                 void apply(osg::MatrixTransform& transform) override;
 | |
|                 void apply(osg::Geometry&) override { }
 | |
| 
 | |
|                 bool removeTransforms(osg::Node* nodeWeCannotRemove);
 | |
| 
 | |
|             protected:
 | |
| 
 | |
|                 typedef std::set<osg::MatrixTransform*> TransformSet;
 | |
|                 TransformSet  _transformSet;
 | |
|         };
 | |
| 
 | |
|         /** Remove rendundant nodes, such as groups with one single child.*/
 | |
|         class RemoveEmptyNodesVisitor : public BaseOptimizerVisitor
 | |
|         {
 | |
|             public:
 | |
| 
 | |
| 
 | |
|                 typedef std::set<osg::Node*> NodeList;
 | |
|                 NodeList                     _redundantNodeList;
 | |
| 
 | |
|                 RemoveEmptyNodesVisitor(Optimizer* optimizer=0):
 | |
|                     BaseOptimizerVisitor(optimizer, REMOVE_REDUNDANT_NODES) {}
 | |
| 
 | |
|                 void apply(osg::Group& group) override;
 | |
|                 void apply(osg::Geometry&) override { }
 | |
| 
 | |
|                 void removeEmptyNodes();
 | |
| 
 | |
|         };
 | |
| 
 | |
|         /** Remove redundant nodes, such as groups with one single child.*/
 | |
|         class RemoveRedundantNodesVisitor : public BaseOptimizerVisitor
 | |
|         {
 | |
|             public:
 | |
| 
 | |
|                 typedef std::set<osg::Node*> NodeList;
 | |
|                 NodeList                     _redundantNodeList;
 | |
| 
 | |
|                 RemoveRedundantNodesVisitor(Optimizer* optimizer=0):
 | |
|                     BaseOptimizerVisitor(optimizer, REMOVE_REDUNDANT_NODES) {}
 | |
| 
 | |
|                 void apply(osg::Group& group) override;
 | |
|                 void apply(osg::Transform& transform) override;
 | |
|                 void apply(osg::LOD& lod) override;
 | |
|                 void apply(osg::Switch& switchNode) override;
 | |
|                 void apply(osg::Sequence& sequenceNode) override;
 | |
|                 void apply(osg::Geometry&) override { }
 | |
| 
 | |
|                 bool isOperationPermissible(osg::Node& node);
 | |
| 
 | |
|                 void removeRedundantNodes();
 | |
| 
 | |
|         };
 | |
| 
 | |
|         /** Merge adjacent Groups that have the same StateSet. */
 | |
|         class MergeGroupsVisitor : public SceneUtil::BaseOptimizerVisitor
 | |
|         {
 | |
|         public:
 | |
|             MergeGroupsVisitor(SceneUtil::Optimizer* optimizer)
 | |
|                 : BaseOptimizerVisitor(optimizer, REMOVE_REDUNDANT_NODES)
 | |
|             {
 | |
|             }
 | |
| 
 | |
|             bool isOperationPermissible(osg::Group& node);
 | |
| 
 | |
|             void apply(osg::Geometry&) override { }
 | |
|             void apply(osg::Group& group) override;
 | |
|             void apply(osg::LOD& lod) override;
 | |
|             void apply(osg::Switch& switchNode) override;
 | |
|             void apply(osg::Sequence& sequenceNode) override;
 | |
|         };
 | |
| 
 | |
|         class MergeGeometryVisitor : public BaseOptimizerVisitor
 | |
|         {
 | |
|             public:
 | |
| 
 | |
|                 /// default to traversing all children.
 | |
|                 MergeGeometryVisitor(Optimizer* optimizer=0) :
 | |
|                     BaseOptimizerVisitor(optimizer, MERGE_GEOMETRY),
 | |
|                     _targetMaximumNumberOfVertices(10000), _alphaBlendingActive(false), _mergeAlphaBlending(false) {}
 | |
| 
 | |
|                 void setMergeAlphaBlending(bool merge)
 | |
|                 {
 | |
|                     _mergeAlphaBlending = merge;
 | |
|                 }
 | |
|                 void setViewPoint(const osg::Vec3f& viewPoint)
 | |
|                 {
 | |
|                     _viewPoint = viewPoint;
 | |
|                 }
 | |
| 
 | |
|                 void setTargetMaximumNumberOfVertices(unsigned int num)
 | |
|                 {
 | |
|                     _targetMaximumNumberOfVertices = num;
 | |
|                 }
 | |
| 
 | |
|                 unsigned int getTargetMaximumNumberOfVertices() const
 | |
|                 {
 | |
|                     return _targetMaximumNumberOfVertices;
 | |
|                 }
 | |
| 
 | |
|                 bool pushStateSet(osg::StateSet* stateSet);
 | |
|                 void popStateSet();
 | |
|                 void checkAlphaBlendingActive();
 | |
|                 void apply(osg::Geometry&) override { }
 | |
|                 void apply(osg::Group& group) override;
 | |
|                 void apply(osg::Billboard&) override { /* don't do anything*/ }
 | |
| 
 | |
|                 bool mergeGroup(osg::Group& group);
 | |
| 
 | |
|                 static bool mergeGeometry(osg::Geometry& lhs,osg::Geometry& rhs);
 | |
| 
 | |
|                 static bool mergePrimitive(osg::DrawArrays& lhs,osg::DrawArrays& rhs);
 | |
|                 static bool mergePrimitive(osg::DrawArrayLengths& lhs,osg::DrawArrayLengths& rhs);
 | |
|                 static bool mergePrimitive(osg::DrawElementsUByte& lhs,osg::DrawElementsUByte& rhs);
 | |
|                 static bool mergePrimitive(osg::DrawElementsUShort& lhs,osg::DrawElementsUShort& rhs);
 | |
|                 static bool mergePrimitive(osg::DrawElementsUInt& lhs,osg::DrawElementsUInt& rhs);
 | |
| 
 | |
|             protected:
 | |
| 
 | |
|                 unsigned int _targetMaximumNumberOfVertices;
 | |
|                 std::vector<osg::StateSet*> _stateSetStack;
 | |
|                 bool _alphaBlendingActive;
 | |
|                 bool _mergeAlphaBlending;
 | |
|                 osg::Vec3f _viewPoint;
 | |
|         };
 | |
| 
 | |
| };
 | |
| 
 | |
| inline bool BaseOptimizerVisitor::isOperationPermissibleForObject(const osg::StateSet* object) const
 | |
| {
 | |
|     return _optimizer ? _optimizer->isOperationPermissibleForObject(object,_operationType) :  true;
 | |
| }
 | |
| 
 | |
| inline bool BaseOptimizerVisitor::isOperationPermissibleForObject(const osg::StateAttribute* object) const
 | |
| {
 | |
|     return _optimizer ? _optimizer->isOperationPermissibleForObject(object,_operationType) :  true;
 | |
| }
 | |
| 
 | |
| inline bool BaseOptimizerVisitor::isOperationPermissibleForObject(const osg::Drawable* object) const
 | |
| {
 | |
|     return _optimizer ? _optimizer->isOperationPermissibleForObject(object,_operationType) :  true;
 | |
| }
 | |
| 
 | |
| inline bool BaseOptimizerVisitor::isOperationPermissibleForObject(const osg::Node* object) const
 | |
| {
 | |
|     return _optimizer ? _optimizer->isOperationPermissibleForObject(object,_operationType) :  true;
 | |
| }
 | |
| 
 | |
| }
 | |
| 
 | |
| #endif
 | |
| // clang-format on
 |