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

Revision 13041, 34.0 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
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 OSGUTIL_OPTIMIZER
15#define OSGUTIL_OPTIMIZER
16
17#include <osg/NodeVisitor>
18#include <osg/Matrix>
19#include <osg/Geometry>
20#include <osg/Transform>
21#include <osg/Texture2D>
22
23#include <osgUtil/Export>
24
25#include <set>
26
27namespace osgUtil {
28
29// forward declare
30class Optimizer;
31
32/** Helper base class for implementing Optimizer techniques.*/
33class OSGUTIL_EXPORT BaseOptimizerVisitor : public osg::NodeVisitor
34{
35    public:
36
37        BaseOptimizerVisitor(Optimizer* optimizer, unsigned int operation):
38            osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
39            _optimizer(optimizer),
40            _operationType(operation)
41        {
42            setNodeMaskOverride(0xffffffff);
43        }
44
45        inline bool isOperationPermissibleForObject(const osg::StateSet* object) const;
46        inline bool isOperationPermissibleForObject(const osg::StateAttribute* object) const;
47        inline bool isOperationPermissibleForObject(const osg::Drawable* object) const;
48        inline bool isOperationPermissibleForObject(const osg::Node* object) const;
49
50    protected:
51
52        Optimizer*      _optimizer;
53        unsigned int _operationType;
54};
55
56/** Traverses scene graph to improve efficiency. See OptimizationOptions.
57  * For example of usage see examples/osgimpostor or osgviewer.
58  */
59
60class OSGUTIL_EXPORT Optimizer
61{
62
63    public:
64
65        Optimizer() {}
66        virtual ~Optimizer() {}
67
68        enum OptimizationOptions
69        {
70            FLATTEN_STATIC_TRANSFORMS = (1 << 0),
71            REMOVE_REDUNDANT_NODES =    (1 << 1),
72            REMOVE_LOADED_PROXY_NODES = (1 << 2),
73            COMBINE_ADJACENT_LODS =     (1 << 3),
74            SHARE_DUPLICATE_STATE =     (1 << 4),
75            MERGE_GEOMETRY =            (1 << 5),
76            CHECK_GEOMETRY =            (1 << 6),
77            MAKE_FAST_GEOMETRY =        (1 << 7),
78            SPATIALIZE_GROUPS =         (1 << 8),
79            COPY_SHARED_NODES =         (1 << 9),
80            TRISTRIP_GEOMETRY =         (1 << 10),
81            TESSELLATE_GEOMETRY =       (1 << 11),
82            OPTIMIZE_TEXTURE_SETTINGS = (1 << 12),
83            MERGE_GEODES =              (1 << 13),
84            FLATTEN_BILLBOARDS =        (1 << 14),
85            TEXTURE_ATLAS_BUILDER =     (1 << 15),
86            STATIC_OBJECT_DETECTION =   (1 << 16),
87            FLATTEN_STATIC_TRANSFORMS_DUPLICATING_SHARED_SUBGRAPHS = (1 << 17),
88            INDEX_MESH =                (1 << 18),
89            VERTEX_POSTTRANSFORM =      (1 << 19),
90            VERTEX_PRETRANSFORM =       (1 << 20),
91            DEFAULT_OPTIMIZATIONS = FLATTEN_STATIC_TRANSFORMS |
92                                REMOVE_REDUNDANT_NODES |
93                                REMOVE_LOADED_PROXY_NODES |
94                                COMBINE_ADJACENT_LODS |
95                                SHARE_DUPLICATE_STATE |
96                                MERGE_GEOMETRY |
97                                MAKE_FAST_GEOMETRY |
98                                CHECK_GEOMETRY |
99                                OPTIMIZE_TEXTURE_SETTINGS |
100                                STATIC_OBJECT_DETECTION,
101            ALL_OPTIMIZATIONS = FLATTEN_STATIC_TRANSFORMS_DUPLICATING_SHARED_SUBGRAPHS |
102                                REMOVE_REDUNDANT_NODES |
103                                REMOVE_LOADED_PROXY_NODES |
104                                COMBINE_ADJACENT_LODS |
105                                SHARE_DUPLICATE_STATE |
106                                MERGE_GEODES |
107                                MERGE_GEOMETRY |
108                                MAKE_FAST_GEOMETRY |
109                                CHECK_GEOMETRY |
110                                SPATIALIZE_GROUPS |
111                                COPY_SHARED_NODES |
112                                TRISTRIP_GEOMETRY |
113                                OPTIMIZE_TEXTURE_SETTINGS |
114                                TEXTURE_ATLAS_BUILDER |
115                                STATIC_OBJECT_DETECTION
116        };
117
118        /** Reset internal data to initial state - the getPermissibleOptionsMap is cleared.*/
119        void reset();
120
121        /** Traverse the node and its subgraph with a series of optimization
122          * visitors, specified by the OptimizationOptions.*/
123        void optimize(osg::Node* node);
124
125        /** Traverse the node and its subgraph with a series of optimization
126          * visitors, specified by the OptimizationOptions.*/
127        virtual void optimize(osg::Node* node, unsigned int options);
128
129
130        /** Callback for customizing what operations are permitted on objects in the scene graph.*/
131        struct IsOperationPermissibleForObjectCallback : public osg::Referenced
132        {
133            virtual bool isOperationPermissibleForObjectImplementation(const Optimizer* optimizer, const osg::StateSet* stateset,unsigned int option) const
134            {
135                return optimizer->isOperationPermissibleForObjectImplementation(stateset,option);
136            }
137
138            virtual bool isOperationPermissibleForObjectImplementation(const Optimizer* optimizer, const osg::StateAttribute* attribute,unsigned int option) const
139            {
140                return optimizer->isOperationPermissibleForObjectImplementation(attribute,option);
141            }
142
143            virtual bool isOperationPermissibleForObjectImplementation(const Optimizer* optimizer, const osg::Drawable* drawable,unsigned int option) const
144            {
145                return optimizer->isOperationPermissibleForObjectImplementation(drawable,option);
146            }
147
148            virtual bool isOperationPermissibleForObjectImplementation(const Optimizer* optimizer, const osg::Node* node,unsigned int option) const
149            {
150                return optimizer->isOperationPermissibleForObjectImplementation(node,option);
151            }
152
153        };
154
155        /** Set the callback for customizing what operations are permitted on objects in the scene graph.*/
156        void setIsOperationPermissibleForObjectCallback(IsOperationPermissibleForObjectCallback* callback) { _isOperationPermissibleForObjectCallback=callback; }
157
158        /** Get the callback for customizing what operations are permitted on objects in the scene graph.*/
159        IsOperationPermissibleForObjectCallback* getIsOperationPermissibleForObjectCallback() { return _isOperationPermissibleForObjectCallback.get(); }
160
161        /** Get the callback for customizing what operations are permitted on objects in the scene graph.*/
162        const IsOperationPermissibleForObjectCallback* getIsOperationPermissibleForObjectCallback() const { return _isOperationPermissibleForObjectCallback.get(); }
163
164
165        inline void setPermissibleOptimizationsForObject(const osg::Object* object, unsigned int options)
166        {
167            _permissibleOptimizationsMap[object] = options;
168        }
169
170        inline unsigned int getPermissibleOptimizationsForObject(const osg::Object* object) const
171        {
172            PermissibleOptimizationsMap::const_iterator itr = _permissibleOptimizationsMap.find(object);
173            if (itr!=_permissibleOptimizationsMap.end()) return itr->second;
174            else return 0xffffffff;
175        }
176
177
178        inline bool isOperationPermissibleForObject(const osg::StateSet* object, unsigned int option) const
179        {
180            if (_isOperationPermissibleForObjectCallback.valid())
181                return _isOperationPermissibleForObjectCallback->isOperationPermissibleForObjectImplementation(this,object,option);
182            else
183                return isOperationPermissibleForObjectImplementation(object,option);
184        }
185
186        inline bool isOperationPermissibleForObject(const osg::StateAttribute* object, unsigned int option) const
187        {
188            if (_isOperationPermissibleForObjectCallback.valid())
189                return _isOperationPermissibleForObjectCallback->isOperationPermissibleForObjectImplementation(this,object,option);
190            else
191                return isOperationPermissibleForObjectImplementation(object,option);
192        }
193
194        inline bool isOperationPermissibleForObject(const osg::Drawable* object, unsigned int option) const
195        {
196            if (_isOperationPermissibleForObjectCallback.valid())
197                return _isOperationPermissibleForObjectCallback->isOperationPermissibleForObjectImplementation(this,object,option);
198            else
199                return isOperationPermissibleForObjectImplementation(object,option);
200        }
201
202        inline bool isOperationPermissibleForObject(const osg::Node* object, unsigned int option) const
203        {
204            if (_isOperationPermissibleForObjectCallback.valid())
205                return _isOperationPermissibleForObjectCallback->isOperationPermissibleForObjectImplementation(this,object,option);
206            else
207                return isOperationPermissibleForObjectImplementation(object,option);
208        }
209
210        bool isOperationPermissibleForObjectImplementation(const osg::StateSet* stateset, unsigned int option) const
211        {
212            return (option & getPermissibleOptimizationsForObject(stateset))!=0;
213        }
214
215        bool isOperationPermissibleForObjectImplementation(const osg::StateAttribute* attribute, unsigned int option) const
216        {
217            return (option & getPermissibleOptimizationsForObject(attribute))!=0;
218        }
219
220        bool isOperationPermissibleForObjectImplementation(const osg::Drawable* drawable, unsigned int option) const
221        {
222            if (option & (REMOVE_REDUNDANT_NODES|MERGE_GEOMETRY))
223            {
224                if (drawable->getUserData()) return false;
225                if (drawable->getUpdateCallback()) return false;
226                if (drawable->getEventCallback()) return false;
227                if (drawable->getCullCallback()) return false;
228            }
229            return (option & getPermissibleOptimizationsForObject(drawable))!=0;
230        }
231
232        bool isOperationPermissibleForObjectImplementation(const osg::Node* node, unsigned int option) const
233        {
234            if (option & (REMOVE_REDUNDANT_NODES|COMBINE_ADJACENT_LODS|FLATTEN_STATIC_TRANSFORMS))
235            {
236                if (node->getUserData()) return false;
237                if (node->getUpdateCallback()) return false;
238                if (node->getEventCallback()) return false;
239                if (node->getCullCallback()) return false;
240                if (node->getNumDescriptions()>0) return false;
241                if (node->getStateSet()) return false;
242                if (node->getNodeMask()!=0xffffffff) return false;
243                // if (!node->getName().empty()) return false;
244            }
245
246            return (option & getPermissibleOptimizationsForObject(node))!=0;
247        }
248
249    protected:
250
251        osg::ref_ptr<IsOperationPermissibleForObjectCallback> _isOperationPermissibleForObjectCallback;
252
253        typedef std::map<const osg::Object*,unsigned int> PermissibleOptimizationsMap;
254        PermissibleOptimizationsMap _permissibleOptimizationsMap;
255
256    public:
257
258        /** Flatten Static Transform nodes by applying their transform to the
259          * geometry on the leaves of the scene graph, then removing the
260          * now redundant transforms.  Static transformed Subgraphs that have multiple
261          * parental paths above them are not flattened, if you require this then
262          * the subgraphs have to be duplicated - for this use the
263          * FlattenStaticTransformsDuplicatingSharedSubgraphsVisitor. */
264        class OSGUTIL_EXPORT FlattenStaticTransformsVisitor : public BaseOptimizerVisitor
265        {
266            public:
267
268                FlattenStaticTransformsVisitor(Optimizer* optimizer=0):
269                    BaseOptimizerVisitor(optimizer, FLATTEN_STATIC_TRANSFORMS) {}
270
271                virtual void apply(osg::Node& geode);
272                virtual void apply(osg::Geode& geode);
273                virtual void apply(osg::Billboard& geode);
274                virtual void apply(osg::ProxyNode& node);
275                virtual void apply(osg::PagedLOD& node);
276                virtual void apply(osg::Transform& transform);
277
278                bool removeTransforms(osg::Node* nodeWeCannotRemove);
279
280            protected:
281
282                typedef std::vector<osg::Transform*>                TransformStack;
283                typedef std::set<osg::Drawable*>                    DrawableSet;
284                typedef std::set<osg::Billboard*>                   BillboardSet;
285                typedef std::set<osg::Node* >                       NodeSet;
286                typedef std::set<osg::Transform*>                   TransformSet;
287
288                TransformStack  _transformStack;
289                NodeSet         _excludedNodeSet;
290                DrawableSet     _drawableSet;
291                BillboardSet    _billboardSet;
292                TransformSet    _transformSet;
293        };
294
295        /** FlattenStaticTransformsDuplicatingSharedSubgraphsVisitor is similar to
296          * to FlattenStaticTransformsVisitor in that is desgined to remove static transforms
297          * from the scene graph, pushing down the transforms to the geometry leaves of the scene graph,
298          * but with the difference that any subgraphs that are shared between different transforms
299          * of duplicated and flatten individually.  This results in more static transforms
300          * being removed, but also means that more data is generated, and as a result may
301          * not always be the most appropriate flatten visitor to use.*/
302        class OSGUTIL_EXPORT FlattenStaticTransformsDuplicatingSharedSubgraphsVisitor : public BaseOptimizerVisitor
303        {
304            public:
305
306                FlattenStaticTransformsDuplicatingSharedSubgraphsVisitor(Optimizer* optimizer=0):
307                    BaseOptimizerVisitor(optimizer, FLATTEN_STATIC_TRANSFORMS_DUPLICATING_SHARED_SUBGRAPHS) {}
308
309                virtual void reset();
310
311                virtual void apply(osg::Group& group);
312                virtual void apply(osg::Transform& transform);
313                virtual void apply(osg::LOD& lod);
314                virtual void apply(osg::Geode& geode);
315                virtual void apply(osg::Billboard& billboard);
316
317            protected:
318
319                void transformGeode(osg::Geode& geode);
320                void transformDrawable(osg::Drawable& drawable);
321                void transformBillboard(osg::Billboard& billboard);
322
323                std::vector<osg::Matrix> _matrixStack;
324
325        };
326
327        /** Combine Static Transform nodes that sit above one another.*/
328        class OSGUTIL_EXPORT CombineStaticTransformsVisitor : public BaseOptimizerVisitor
329        {
330            public:
331
332                CombineStaticTransformsVisitor(Optimizer* optimizer=0):
333                    BaseOptimizerVisitor(optimizer, FLATTEN_STATIC_TRANSFORMS) {}
334
335                virtual void apply(osg::MatrixTransform& transform);
336
337                bool removeTransforms(osg::Node* nodeWeCannotRemove);
338
339            protected:
340
341                typedef std::set<osg::MatrixTransform*> TransformSet;
342                TransformSet  _transformSet;
343        };
344
345        /** Remove rendundant nodes, such as groups with one single child.*/
346        class OSGUTIL_EXPORT RemoveEmptyNodesVisitor : public BaseOptimizerVisitor
347        {
348            public:
349
350
351                typedef std::set<osg::Node*> NodeList;
352                NodeList                     _redundantNodeList;
353
354                RemoveEmptyNodesVisitor(Optimizer* optimizer=0):
355                    BaseOptimizerVisitor(optimizer, REMOVE_REDUNDANT_NODES) {}
356
357                virtual void apply(osg::Geode& geode);
358                virtual void apply(osg::Group& group);
359
360                void removeEmptyNodes();
361
362        };
363
364        /** Remove redundant nodes, such as groups with one single child.*/
365        class OSGUTIL_EXPORT RemoveRedundantNodesVisitor : public BaseOptimizerVisitor
366        {
367            public:
368
369                typedef std::set<osg::Node*> NodeList;
370                NodeList                     _redundantNodeList;
371
372                RemoveRedundantNodesVisitor(Optimizer* optimizer=0):
373                    BaseOptimizerVisitor(optimizer, REMOVE_REDUNDANT_NODES) {}
374
375                virtual void apply(osg::Group& group);
376                virtual void apply(osg::Transform& transform);
377
378                bool isOperationPermissible(osg::Node& node);
379
380                void removeRedundantNodes();
381
382        };
383
384        /** Remove loaded proxy nodes.*/
385        class OSGUTIL_EXPORT RemoveLoadedProxyNodesVisitor : public BaseOptimizerVisitor
386        {
387            public:
388
389                typedef std::set<osg::Node*> NodeList;
390                NodeList                     _redundantNodeList;
391
392                RemoveLoadedProxyNodesVisitor(Optimizer* optimizer=0):
393                    BaseOptimizerVisitor(optimizer, REMOVE_LOADED_PROXY_NODES) {}
394
395                virtual void apply(osg::ProxyNode& group);
396
397                void removeRedundantNodes();
398
399        };
400
401        /** Tessellate all geodes, to remove POLYGONS.*/
402        class OSGUTIL_EXPORT TessellateVisitor : public BaseOptimizerVisitor
403        {
404            public:
405
406                typedef std::set<osg::Group*>  GroupList;
407                GroupList                      _groupList;
408
409                TessellateVisitor(Optimizer* optimizer=0):
410                    BaseOptimizerVisitor(optimizer, TESSELLATE_GEOMETRY) {}
411
412                virtual void apply(osg::Geode& geode);
413
414        };
415
416        /** Optimize the LOD groups, by combining adjacent LOD's which have
417          * complementary ranges.*/
418        class OSGUTIL_EXPORT CombineLODsVisitor : public BaseOptimizerVisitor
419        {
420            public:
421
422                typedef std::set<osg::Group*>  GroupList;
423                GroupList                      _groupList;
424
425                CombineLODsVisitor(Optimizer* optimizer=0):
426                    BaseOptimizerVisitor(optimizer, COMBINE_ADJACENT_LODS) {}
427
428                virtual void apply(osg::LOD& lod);
429
430                void combineLODs();
431
432        };
433
434        /** Optimize State in the scene graph by removing duplicate state,
435          * replacing it with shared instances, both for StateAttributes,
436          * and whole StateSets.*/
437        class OSGUTIL_EXPORT StateVisitor : public BaseOptimizerVisitor
438        {
439            public:
440
441                /// default to traversing all children.
442                StateVisitor(bool combineDynamicState,
443                             bool combineStaticState,
444                             bool combineUnspecifiedState,
445                             Optimizer* optimizer=0):
446                    BaseOptimizerVisitor(optimizer, SHARE_DUPLICATE_STATE)
447                {
448                    _optimize[osg::Object::DYNAMIC] = combineDynamicState;
449                    _optimize[osg::Object::STATIC] = combineStaticState;
450                    _optimize[osg::Object::UNSPECIFIED] = combineUnspecifiedState;
451                }
452
453                /** empty visitor, make it ready for next traversal.*/
454                virtual void reset();
455
456                virtual void apply(osg::Node& node);
457
458                virtual void apply(osg::Geode& geode);
459
460                void optimize();
461
462            protected:
463
464                void addStateSet(osg::StateSet* stateset,osg::Object* obj);
465
466                inline bool optimize(osg::Object::DataVariance variance)
467                {
468                    return _optimize[variance];
469                }
470
471                typedef std::set<osg::Object*>              ObjectSet;
472                typedef std::map<osg::StateSet*,ObjectSet>  StateSetMap;
473
474                // note, one element for DYNAMIC, STATIC and UNSPECIFIED
475                bool _optimize[3];
476
477                StateSetMap _statesets;
478
479        };
480
481        /** Combine geodes
482          */
483        class OSGUTIL_EXPORT MergeGeodesVisitor : public BaseOptimizerVisitor
484        {
485            public:
486
487                /// default to traversing all children.
488                MergeGeodesVisitor(Optimizer* optimizer=0):
489                    BaseOptimizerVisitor(optimizer, MERGE_GEODES) {}
490
491                virtual void apply(osg::Group& group);
492
493                bool mergeGeodes(osg::Group& group);
494
495            protected:
496
497                bool mergeGeode(osg::Geode& lhs, osg::Geode& rhs);
498
499        };
500
501        class OSGUTIL_EXPORT CheckGeometryVisitor : public BaseOptimizerVisitor
502        {
503            public:
504
505                /// default to traversing all children.
506                CheckGeometryVisitor(Optimizer* optimizer=0):
507                    BaseOptimizerVisitor(optimizer, CHECK_GEOMETRY) {}
508
509                virtual void apply(osg::Geode& geode) { checkGeode(geode); }
510
511                void checkGeode(osg::Geode& geode);
512
513        };
514
515        class OSGUTIL_EXPORT MakeFastGeometryVisitor : public BaseOptimizerVisitor
516        {
517            public:
518
519                /// default to traversing all children.
520                MakeFastGeometryVisitor(Optimizer* optimizer=0):
521                    BaseOptimizerVisitor(optimizer, MAKE_FAST_GEOMETRY) {}
522
523                virtual void apply(osg::Geode& geode) { checkGeode(geode); }
524
525                void checkGeode(osg::Geode& geode);
526
527        };
528
529        class OSGUTIL_EXPORT MergeGeometryVisitor : public BaseOptimizerVisitor
530        {
531            public:
532
533                /// default to traversing all children.
534                MergeGeometryVisitor(Optimizer* optimizer=0) :
535                    BaseOptimizerVisitor(optimizer, MERGE_GEOMETRY),
536                    _targetMaximumNumberOfVertices(10000) {}
537
538                void setTargetMaximumNumberOfVertices(unsigned int num)
539                {
540                    _targetMaximumNumberOfVertices = num;
541                }
542
543                unsigned int getTargetMaximumNumberOfVertices() const
544                {
545                    return _targetMaximumNumberOfVertices;
546                }
547
548                virtual void apply(osg::Geode& geode) { mergeGeode(geode); }
549                virtual void apply(osg::Billboard&) { /* don't do anything*/ }
550
551                bool mergeGeode(osg::Geode& geode);
552
553                static bool geometryContainsSharedArrays(osg::Geometry& geom);
554
555                static bool mergeGeometry(osg::Geometry& lhs,osg::Geometry& rhs);
556
557                static bool mergePrimitive(osg::DrawArrays& lhs,osg::DrawArrays& rhs);
558                static bool mergePrimitive(osg::DrawArrayLengths& lhs,osg::DrawArrayLengths& rhs);
559                static bool mergePrimitive(osg::DrawElementsUByte& lhs,osg::DrawElementsUByte& rhs);
560                static bool mergePrimitive(osg::DrawElementsUShort& lhs,osg::DrawElementsUShort& rhs);
561                static bool mergePrimitive(osg::DrawElementsUInt& lhs,osg::DrawElementsUInt& rhs);
562
563            protected:
564
565                unsigned int _targetMaximumNumberOfVertices;
566
567        };
568
569        /** Spatialize scene into a balanced quad/oct tree.*/
570        class OSGUTIL_EXPORT SpatializeGroupsVisitor : public BaseOptimizerVisitor
571        {
572            public:
573
574                SpatializeGroupsVisitor(Optimizer* optimizer=0):
575                    BaseOptimizerVisitor(optimizer, SPATIALIZE_GROUPS) {}
576
577                virtual void apply(osg::Group& group);
578                virtual void apply(osg::Geode& geode);
579
580                bool divide(unsigned int maxNumTreesPerCell=8);
581
582                bool divide(osg::Group* group, unsigned int maxNumTreesPerCell);
583                bool divide(osg::Geode* geode, unsigned int maxNumTreesPerCell);
584
585                typedef std::set<osg::Group*> GroupsToDivideList;
586                GroupsToDivideList _groupsToDivideList;
587
588                typedef std::set<osg::Geode*> GeodesToDivideList;
589                GeodesToDivideList _geodesToDivideList;
590        };
591
592        /** Copy any shared subgraphs, enabling flattening of static transforms.*/
593        class OSGUTIL_EXPORT CopySharedSubgraphsVisitor : public BaseOptimizerVisitor
594        {
595            public:
596
597                CopySharedSubgraphsVisitor(Optimizer* optimizer=0):
598                    BaseOptimizerVisitor(optimizer, COPY_SHARED_NODES) {}
599
600                virtual void apply(osg::Node& node);
601
602                void copySharedNodes();
603
604                typedef std::set<osg::Node*> SharedNodeList;
605                SharedNodeList _sharedNodeList;
606
607        };
608
609
610        /** For all textures apply settings.*/
611        class OSGUTIL_EXPORT TextureVisitor : public BaseOptimizerVisitor
612        {
613            public:
614
615                TextureVisitor(bool changeAutoUnRef, bool valueAutoUnRef,
616                               bool changeClientImageStorage, bool valueClientImageStorage,
617                               bool changeAnisotropy, float valueAnisotropy,
618                               Optimizer* optimizer=0):
619                        BaseOptimizerVisitor(optimizer, OPTIMIZE_TEXTURE_SETTINGS),
620                        _changeAutoUnRef(changeAutoUnRef), _valueAutoUnRef(valueAutoUnRef),
621                        _changeClientImageStorage(changeClientImageStorage), _valueClientImageStorage(valueClientImageStorage),
622                        _changeAnisotropy(changeAnisotropy), _valueAnisotropy(valueAnisotropy) {}
623
624                virtual void apply(osg::Geode& node);
625                virtual void apply(osg::Node& node);
626
627                void apply(osg::StateSet& stateset);
628                void apply(osg::Texture& texture);
629
630                bool            _changeAutoUnRef, _valueAutoUnRef;
631                bool            _changeClientImageStorage, _valueClientImageStorage;
632                bool            _changeAnisotropy;
633                float           _valueAnisotropy;
634
635        };
636
637        /** Flatten MatrixTransform/Billboard pairs.*/
638        class OSGUTIL_EXPORT FlattenBillboardVisitor : public BaseOptimizerVisitor
639        {
640            public:
641                FlattenBillboardVisitor(Optimizer* optimizer=0):
642                        BaseOptimizerVisitor(optimizer, FLATTEN_BILLBOARDS) {}
643
644                typedef std::vector<osg::NodePath> NodePathList;
645                typedef std::map<osg::Billboard*, NodePathList > BillboardNodePathMap;
646
647                virtual void reset();
648
649                virtual void apply(osg::Billboard& billboard);
650
651                void process();
652
653                BillboardNodePathMap _billboards;
654
655        };
656
657        /** Texture Atlas Builder creates a set of textures/images which each contain multiple images.
658          * Texture Atlas' are used to make it possible to use much wider batching of data. */
659        class OSGUTIL_EXPORT TextureAtlasBuilder
660        {
661        public:
662            TextureAtlasBuilder();
663
664            void reset();
665
666            void setMaximumAtlasSize(int width, int height);
667
668            int getMaximumAtlasWidth() const { return _maximumAtlasWidth; }
669            int getMaximumAtlasHeight() const { return _maximumAtlasHeight; }
670
671            void setMargin(int margin);
672            int getMargin() const { return _margin; }
673
674            void addSource(const osg::Image* image);
675            void addSource(const osg::Texture2D* texture);
676
677            unsigned int getNumSources() const { return _sourceList.size(); }
678            const osg::Image* getSourceImage(unsigned int i) { return _sourceList[i]->_image.get(); }
679            const osg::Texture2D* getSourceTexture(unsigned int i) { return _sourceList[i]->_texture.get(); }
680
681            void buildAtlas();
682            osg::Image* getImageAtlas(unsigned int i);
683            osg::Texture2D* getTextureAtlas(unsigned int i);
684            osg::Matrix getTextureMatrix(unsigned int i);
685
686            osg::Image* getImageAtlas(const osg::Image* image);
687            osg::Texture2D* getTextureAtlas(const osg::Image* image);
688            osg::Matrix getTextureMatrix(const osg::Image* image);
689
690            osg::Image* getImageAtlas(const osg::Texture2D* textue);
691            osg::Texture2D* getTextureAtlas(const osg::Texture2D* texture);
692            osg::Matrix getTextureMatrix(const osg::Texture2D* texture);
693
694        protected:
695
696            int _maximumAtlasWidth;
697            int _maximumAtlasHeight;
698            int _margin;
699
700
701            // forward declare
702            class Atlas;
703
704            class Source : public osg::Referenced
705            {
706            public:
707                Source():
708                    _x(0),_y(0),_atlas(0) {}
709
710                Source(const osg::Image* image):
711                    _x(0),_y(0),_atlas(0),_image(image) {}
712
713                Source(const osg::Texture2D* texture):
714                    _x(0),_y(0),_atlas(0),_texture(texture) { if (texture) _image = texture->getImage(); }
715
716                int _x;
717                int _y;
718                Atlas* _atlas;
719
720                osg::ref_ptr<const osg::Image> _image;
721                osg::ref_ptr<const osg::Texture2D> _texture;
722
723                bool suitableForAtlas(int maximumAtlasWidth, int maximumAtlasHeight, int margin);
724                osg::Matrix computeTextureMatrix() const;
725
726
727            protected:
728
729                virtual ~Source() {}
730            };
731
732            typedef std::vector< osg::ref_ptr<Source> > SourceList;
733
734            class Atlas : public osg::Referenced
735            {
736            public:
737                Atlas(int width, int height, int margin):
738                    _maximumAtlasWidth(width),
739                    _maximumAtlasHeight(height),
740                    _margin(margin),
741                    _x(0),
742                    _y(0),
743                    _width(0),
744                    _height(0),
745                    _indexFirstOfRow(0){}
746
747                int _maximumAtlasWidth;
748                int _maximumAtlasHeight;
749                int _margin;
750
751                osg::ref_ptr<osg::Texture2D> _texture;
752                osg::ref_ptr<osg::Image> _image;
753
754                SourceList _sourceList;
755
756                int _x;
757                int _y;
758                int _width;
759                int _height;
760                unsigned int _indexFirstOfRow; ///< Contain the index of the first element of the last row.
761                enum FitsIn
762                {
763                    DOES_NOT_FIT_IN_ANY_ROW,
764                    FITS_IN_CURRENT_ROW,
765                    IN_NEXT_ROW
766                };
767                FitsIn doesSourceFit(Source* source);
768                bool addSource(Source* source);
769                void clampToNearestPowerOfTwoSize();
770                void copySources();
771
772            protected:
773                virtual ~Atlas() {}
774            };
775
776            typedef std::vector< osg::ref_ptr<Atlas> > AtlasList;
777
778            Source* getSource(const osg::Image* image);
779            Source* getSource(const osg::Texture2D* texture);
780
781            SourceList _sourceList;
782            AtlasList _atlasList;
783            private:
784                struct CompareSrc
785                {
786                    bool operator()(osg::ref_ptr<Source> src1, osg::ref_ptr<Source> src2) const
787                    {
788                        return src1->_image->t() > src2->_image->t();
789                    }
790                };
791                void completeRow(unsigned int indexAtlas);
792        };
793
794
795        /** Optimize texture usage in the scene graph by combining textures into texture atlas
796          * Use of texture atlas cuts down on the number of seperate states in the scene, reducing
797          * state changes and improving the chances of use larger batches of geomertry.*/
798        class OSGUTIL_EXPORT TextureAtlasVisitor : public BaseOptimizerVisitor
799        {
800            public:
801
802                /// default to traversing all children.
803                TextureAtlasVisitor(Optimizer* optimizer=0):
804                    BaseOptimizerVisitor(optimizer, TEXTURE_ATLAS_BUILDER) {}
805
806
807                TextureAtlasBuilder& getTextureAtlasBuilder() { return _builder; }
808
809                /** empty visitor, make it ready for next traversal.*/
810                virtual void reset();
811
812                virtual void apply(osg::Node& node);
813
814                virtual void apply(osg::Geode& geode);
815
816                void optimize();
817
818            protected:
819
820                bool pushStateSet(osg::StateSet* stateset);
821                void popStateSet();
822
823                typedef std::set<osg::Drawable*>  Drawables;
824                typedef std::map<osg::StateSet*, Drawables>  StateSetMap;
825                typedef std::set<osg::Texture2D*>  Textures;
826                typedef std::vector<osg::StateSet*>  StateSetStack;
827
828                TextureAtlasBuilder _builder;
829
830                StateSetMap     _statesetMap;
831                StateSetStack   _statesetStack;
832                Textures        _textures;
833
834        };
835
836        /** Optimize the setting of StateSet and Geometry objects in scene so that they have a STATIC DataVariance
837          * when they don't have any callbacks associated with them. */
838        class OSGUTIL_EXPORT StaticObjectDetectionVisitor : public BaseOptimizerVisitor
839        {
840            public:
841
842                /// default to traversing all children.
843                StaticObjectDetectionVisitor(Optimizer* optimizer=0):
844                    BaseOptimizerVisitor(optimizer, STATIC_OBJECT_DETECTION) {}
845
846                virtual void apply(osg::Node& node);
847
848                virtual void apply(osg::Geode& geode);
849
850            protected:
851
852                void applyStateSet(osg::StateSet& stateset);
853
854                void applyDrawable(osg::Drawable& drawable);
855
856        };
857};
858
859inline bool BaseOptimizerVisitor::isOperationPermissibleForObject(const osg::StateSet* object) const
860{
861    return _optimizer ? _optimizer->isOperationPermissibleForObject(object,_operationType) :  true;
862}
863
864inline bool BaseOptimizerVisitor::isOperationPermissibleForObject(const osg::StateAttribute* object) const
865{
866    return _optimizer ? _optimizer->isOperationPermissibleForObject(object,_operationType) :  true;
867}
868
869inline bool BaseOptimizerVisitor::isOperationPermissibleForObject(const osg::Drawable* object) const
870{
871    return _optimizer ? _optimizer->isOperationPermissibleForObject(object,_operationType) :  true;
872}
873
874inline bool BaseOptimizerVisitor::isOperationPermissibleForObject(const osg::Node* object) const
875{
876    return _optimizer ? _optimizer->isOperationPermissibleForObject(object,_operationType) :  true;
877}
878
879}
880
881#endif
Note: See TracBrowser for help on using the browser.