root/OpenSceneGraph/trunk/include/osgUtil/Optimizer @ 3526

Revision 3432, 17.6 kB (checked in by robert, 13 years ago)

From Geoff Michel, typos and spelling fixes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 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 OSGUTIL_OPTIMIZER
15#define OSGUTIL_OPTIMIZER
16
17#include <osg/NodeVisitor>
18#include <osg/Matrix>
19#include <osg/Geometry>
20#include <osg/Transform>
21
22#include <osgUtil/Export>
23
24#include <set>
25
26namespace osgUtil {
27
28/** Traverses scene graph to improve efficiency. See OptimizationOptions.
29  * For example of usage see examples/osgimpostor or osgviewer.
30  */
31 
32class OSGUTIL_EXPORT Optimizer
33{
34
35    public:
36
37        Optimizer() {}
38        virtual ~Optimizer() {}
39
40        enum OptimizationOptions
41        {
42            FLATTEN_STATIC_TRANSFORMS = 0x001,
43            REMOVE_REDUNDANT_NODES =    0x002,
44            COMBINE_ADJACENT_LODS =     0x004,
45            SHARE_DUPLICATE_STATE =     0x008,
46            MERGE_GEOMETRY =            0x010,
47            CHECK_GEOMETRY =            0x020,
48            SPATIALIZE_GROUPS =         0x040,
49            COPY_SHARED_NODES =         0x080,
50            TRISTRIP_GEOMETRY =         0x100,
51            TESSELATE_GEOMETRY =        0x200,
52            OPTIMIZE_TEXTURE_SETTINGS = 0x400,
53            DEFAULT_OPTIMIZATIONS = FLATTEN_STATIC_TRANSFORMS |
54                                REMOVE_REDUNDANT_NODES |
55                                COMBINE_ADJACENT_LODS |
56                                SHARE_DUPLICATE_STATE |
57                                MERGE_GEOMETRY |
58                                CHECK_GEOMETRY |
59                                OPTIMIZE_TEXTURE_SETTINGS,
60            ALL_OPTIMIZATIONS = FLATTEN_STATIC_TRANSFORMS |
61                                REMOVE_REDUNDANT_NODES |
62                                COMBINE_ADJACENT_LODS |
63                                SHARE_DUPLICATE_STATE |
64                                MERGE_GEOMETRY |
65                                CHECK_GEOMETRY |
66                                SPATIALIZE_GROUPS |
67                                COPY_SHARED_NODES |
68                                TRISTRIP_GEOMETRY |
69                                OPTIMIZE_TEXTURE_SETTINGS
70        };
71
72        /** Reset internal data to initial state - the getPermissibleOptionsMap is cleared.*/
73        void reset();
74       
75        /** Traverse the node and its subgraph with a series of optimization
76          * visitors, specified by the OptimizationOptions.*/
77        void optimize(osg::Node* node);
78
79        /** Traverse the node and its subgraph with a series of optimization
80          * visitors, specified by the OptimizationOptions.*/
81        virtual void optimize(osg::Node* node, unsigned int options);
82
83
84        inline void setPermissibleOptimizationsForObject(const osg::Object* object, unsigned int options)
85        {
86            _permissibleOptimizationsMap[object] = options;
87        }
88       
89        inline unsigned int getPermissibleOptimizationsForObject(const osg::Object* object) const
90        {
91            PermissibleOptimizationsMap::const_iterator itr = _permissibleOptimizationsMap.find(object);
92            if (itr!=_permissibleOptimizationsMap.end()) return itr->second;
93            else return 0xffffffff;
94        }
95       
96        inline bool isOperationPermissibleForObject(const osg::Object* object,unsigned int option) const
97        {
98            return (option & getPermissibleOptimizationsForObject(object))!=0;
99        }
100       
101        typedef std::map<const osg::Object*,unsigned int> PermissibleOptimizationsMap;
102
103        PermissibleOptimizationsMap& getPermissibleOptionsMap() { return _permissibleOptimizationsMap; }
104        const PermissibleOptimizationsMap& getPermissibleOptionsMap() const { return _permissibleOptimizationsMap; }
105       
106       
107    protected:
108   
109        PermissibleOptimizationsMap _permissibleOptimizationsMap;
110
111
112    public:
113
114
115        /** Flatten Static Transform nodes by applying their transform to the
116          * geometry on the leaves of the scene graph, then removing the
117          * now redundant transforms.*/       
118        class OSGUTIL_EXPORT FlattenStaticTransformsVisitor : public osg::NodeVisitor
119        {
120            public:
121
122
123
124                FlattenStaticTransformsVisitor(Optimizer* optimizer=0):
125                    osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
126                    _optimizer(optimizer) {}
127
128                virtual void apply(osg::Node& geode);
129                virtual void apply(osg::Geode& geode);
130                virtual void apply(osg::Billboard& geode);
131                virtual void apply(osg::Transform& transform);
132
133                bool removeTransforms(osg::Node* nodeWeCannotRemove);
134
135                inline bool isOperationPermissibleForObject(const osg::Object* object) const
136                {
137                    return _optimizer ? _optimizer->isOperationPermissibleForObject(object,FLATTEN_STATIC_TRANSFORMS) :  true;
138                }
139
140           
141            protected:
142
143                typedef std::vector<osg::Transform*>                TransformStack;
144                typedef std::set<osg::Drawable*>                    DrawableSet;
145                typedef std::set<osg::Billboard*>                   BillboardSet;
146                typedef std::set<osg::Node* >                       NodeSet;
147                typedef std::set<osg::Transform*>                   TransformSet;
148               
149                Optimizer*      _optimizer;
150                TransformStack  _transformStack;
151                NodeSet         _excludedNodeSet;
152                DrawableSet     _drawableSet;
153                BillboardSet    _billboardSet;
154                TransformSet    _transformSet;
155        };
156
157
158        /** Combine Static Transform nodes that sit above one another.*/       
159        class OSGUTIL_EXPORT CombineStaticTransformsVisitor : public osg::NodeVisitor
160        {
161            public:
162
163                CombineStaticTransformsVisitor(Optimizer* optimizer=0):
164                    osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
165                    _optimizer(optimizer) {}
166
167                virtual void apply(osg::MatrixTransform& transform);
168
169                bool removeTransforms(osg::Node* nodeWeCannotRemove);
170
171                inline bool isOperationPermissibleForObject(const osg::Object* object) const
172                {
173                    return _optimizer ? _optimizer->isOperationPermissibleForObject(object,FLATTEN_STATIC_TRANSFORMS) :  true;
174                }
175
176            protected:
177
178                typedef std::set<osg::MatrixTransform*> TransformSet;
179                Optimizer*      _optimizer;
180                TransformSet  _transformSet;
181        };
182
183        /** Remove rendundant nodes, such as groups with one single child.*/
184        class OSGUTIL_EXPORT RemoveEmptyNodesVisitor : public osg::NodeVisitor
185        {
186            public:
187
188
189                typedef std::set<osg::Node*> NodeList;
190                NodeList                     _redundantNodeList;
191
192                RemoveEmptyNodesVisitor(Optimizer* optimizer=0):
193                    osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
194                    _optimizer(optimizer) {}
195
196                virtual void apply(osg::Geode& geode);
197                virtual void apply(osg::Group& group);
198               
199                void removeEmptyNodes();
200
201                inline bool isOperationPermissibleForObject(const osg::Object* object) const
202                {
203                    return _optimizer ? _optimizer->isOperationPermissibleForObject(object,REMOVE_REDUNDANT_NODES) :  true;
204                }
205
206                Optimizer*      _optimizer;
207        };
208
209        /** Remove rendundant nodes, such as groups with one single child.*/
210        class OSGUTIL_EXPORT RemoveRedundantNodesVisitor : public osg::NodeVisitor
211        {
212            public:
213
214                typedef std::set<osg::Node*> NodeList;
215                NodeList                     _redundantNodeList;
216
217                RemoveRedundantNodesVisitor(Optimizer* optimizer=0):
218                    osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
219                    _optimizer(optimizer) {}
220               
221                virtual void apply(osg::Group& group);
222                virtual void apply(osg::Transform& transform);
223               
224                void removeRedundantNodes();
225
226                inline bool isOperationPermissibleForObject(const osg::Object* object) const
227                {
228                    return _optimizer ? _optimizer->isOperationPermissibleForObject(object,REMOVE_REDUNDANT_NODES) :  true;
229                }
230
231                Optimizer*      _optimizer;
232        };
233
234        /** Tesselate all geodes, to remove POLYGONS.*/
235        class OSGUTIL_EXPORT TesselateVisitor : public osg::NodeVisitor
236        {
237            public:
238
239                typedef std::set<osg::Group*>  GroupList;
240                GroupList                      _groupList;
241
242                TesselateVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
243
244                virtual void apply(osg::Geode& geode);
245
246        };
247
248        /** Optimize the LOD groups, by combining adjacent LOD's which have
249          * complementary ranges.*/
250        class OSGUTIL_EXPORT CombineLODsVisitor : public osg::NodeVisitor
251        {
252            public:
253
254                typedef std::set<osg::Group*>  GroupList;
255                GroupList                      _groupList;
256
257                CombineLODsVisitor(Optimizer* optimizer=0):
258                    osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
259                    _optimizer(optimizer) {}
260
261                virtual void apply(osg::LOD& lod);
262
263                void combineLODs();
264
265                inline bool isOperationPermissibleForObject(const osg::Object* object) const
266                {
267                    return _optimizer ? _optimizer->isOperationPermissibleForObject(object,COMBINE_ADJACENT_LODS) :  true;
268                }
269
270                Optimizer*      _optimizer;
271        };
272 
273        /** Optimize State in the scene graph by removing duplicate state,
274          * replacing it with shared instances, both for StateAttributes,
275          * and whole StateSets.*/
276        class OSGUTIL_EXPORT StateVisitor : public osg::NodeVisitor
277        {
278            public:
279
280                /// default to traversing all children.
281                StateVisitor(Optimizer* optimizer=0):
282                    osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
283                    _optimizer(optimizer) {}
284
285                /** empty visitor, make it ready for next traversal.*/       
286                virtual void reset();
287
288                virtual void apply(osg::Node& node);
289
290                virtual void apply(osg::Geode& geode);
291
292                void optimize();
293
294                inline bool isOperationPermissibleForObject(const osg::Object* object) const
295                {
296                    return _optimizer ? _optimizer->isOperationPermissibleForObject(object,SHARE_DUPLICATE_STATE) :  true;
297                }
298
299            protected:
300
301                void addStateSet(osg::StateSet* stateset,osg::Object* obj);
302
303                typedef std::set<osg::Object*>              ObjectSet;
304                typedef std::map<osg::StateSet*,ObjectSet>  StateSetMap;
305
306                Optimizer*      _optimizer;
307                StateSetMap _statesets;
308
309        };
310       
311        class OSGUTIL_EXPORT CheckGeometryVisitor : public osg::NodeVisitor
312        {
313            public:
314
315                /// default to traversing all children.
316                CheckGeometryVisitor(Optimizer* optimizer=0):
317                    osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
318                    _optimizer(optimizer) {}
319
320                virtual void apply(osg::Geode& geode) { checkGeode(geode); }
321
322                void checkGeode(osg::Geode& geode);
323               
324                inline bool isOperationPermissibleForObject(const osg::Object* object) const
325                {
326                    return _optimizer ? _optimizer->isOperationPermissibleForObject(object,CHECK_GEOMETRY) :  true;
327                }
328
329                Optimizer*      _optimizer;
330
331        };
332       
333        class OSGUTIL_EXPORT MergeGeometryVisitor : public osg::NodeVisitor
334        {
335            public:
336
337                /// default to traversing all children.
338                MergeGeometryVisitor(Optimizer* optimizer=0) :
339                    osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
340                    _optimizer(optimizer) {}
341
342                virtual void apply(osg::Geode& geode) { mergeGeode(geode); }
343                virtual void apply(osg::Billboard&) { /* don't do anything*/ }
344
345                bool mergeGeode(osg::Geode& geode);
346
347                static bool geometryContainsSharedArrays(osg::Geometry& geom);
348
349                static bool mergeGeometry(osg::Geometry& lhs,osg::Geometry& rhs);
350
351                static bool mergePrimitive(osg::DrawArrays& lhs,osg::DrawArrays& rhs);
352                static bool mergePrimitive(osg::DrawArrayLengths& lhs,osg::DrawArrayLengths& rhs);
353                static bool mergePrimitive(osg::DrawElementsUByte& lhs,osg::DrawElementsUByte& rhs);
354                static bool mergePrimitive(osg::DrawElementsUShort& lhs,osg::DrawElementsUShort& rhs);
355                static bool mergePrimitive(osg::DrawElementsUInt& lhs,osg::DrawElementsUInt& rhs);
356
357                inline bool isOperationPermissibleForObject(const osg::Object* object) const
358                {
359                    return _optimizer ? _optimizer->isOperationPermissibleForObject(object,MERGE_GEOMETRY) :  true;
360                }
361
362                Optimizer*      _optimizer;
363        };
364
365        /** Spatialize scene into a balanced quad/oct tree.*/
366        class OSGUTIL_EXPORT SpatializeGroupsVisitor : public osg::NodeVisitor
367        {
368            public:
369
370                SpatializeGroupsVisitor(Optimizer* optimizer=0):
371                    osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
372                    _optimizer(optimizer) {}
373               
374                virtual void apply(osg::Group& group);
375               
376                bool divide(unsigned int maxNumTreesPerCell=8);
377               
378                bool divide(osg::Group* group, unsigned int maxNumTreesPerCell);
379               
380                typedef std::set<osg::Group*> GroupsToDivideList;
381                GroupsToDivideList _groupsToDivideList;
382
383                inline bool isOperationPermissibleForObject(const osg::Object* object) const
384                {
385                    return _optimizer ? _optimizer->isOperationPermissibleForObject(object,SPATIALIZE_GROUPS) :  true;
386                }
387
388                Optimizer*      _optimizer;
389
390        };
391
392        /** Copy any shared subgraphs, enabling flattening of static transforms.*/
393        class OSGUTIL_EXPORT CopySharedSubgraphsVisitor : public osg::NodeVisitor
394        {
395            public:
396
397                CopySharedSubgraphsVisitor(Optimizer* optimizer=0):
398                    osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
399                    _optimizer(optimizer) {}
400               
401                virtual void apply(osg::Node& node);
402
403                void copySharedNodes();
404               
405                typedef std::set<osg::Node*> SharedNodeList;
406                SharedNodeList _sharedNodeList;
407               
408                inline bool isOperationPermissibleForObject(const osg::Object* object) const
409                {
410                    return _optimizer ? _optimizer->isOperationPermissibleForObject(object,COPY_SHARED_NODES) :  true;
411                }
412
413                Optimizer*      _optimizer;
414
415        };
416
417
418        /** For all textures apply settings.*/
419        class OSGUTIL_EXPORT TextureVisitor : public osg::NodeVisitor
420        {
421            public:
422
423                TextureVisitor(bool changeAutoUnRef, bool valueAutoUnRef,
424                               bool changeClientImageStorage, bool valueClientImageStorage,
425                               bool changeAnisotropy, float valueAnisotropy,
426                               Optimizer* optimizer=0):
427                        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
428                        _optimizer(optimizer),
429                        _changeAutoUnRef(changeAutoUnRef), _valueAutoUnRef(valueAutoUnRef),
430                        _changeClientImageStorage(changeClientImageStorage), _valueClientImageStorage(valueClientImageStorage),
431                        _changeAnisotropy(changeAnisotropy), _valueAnisotropy(valueAnisotropy) {}
432               
433                virtual void apply(osg::Geode& node);
434                virtual void apply(osg::Node& node);
435
436                void apply(osg::StateSet& stateset);
437                void apply(osg::Texture& texture);
438               
439                inline bool isOperationPermissibleForObject(const osg::Object* object) const
440                {
441                    return _optimizer ? _optimizer->isOperationPermissibleForObject(object,OPTIMIZE_TEXTURE_SETTINGS) :  true;
442                }
443
444                Optimizer*      _optimizer;
445                bool            _changeAutoUnRef, _valueAutoUnRef;
446                bool            _changeClientImageStorage, _valueClientImageStorage;
447                bool            _changeAnisotropy;
448                float           _valueAnisotropy;
449                                           
450               
451
452        };
453
454};
455
456}
457
458#endif
Note: See TracBrowser for help on using the browser.