]> git.mxchange.org Git - simgear.git/blob - simgear/scene/material/Effect.hxx
Merge branch 'zan/stencil'
[simgear.git] / simgear / scene / material / Effect.hxx
1 // Copyright (C) 2008 - 2009  Tim Moore timoore@redhat.com
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Library General Public
5 // License as published by the Free Software Foundation; either
6 // version 2 of the License, or (at your option) any later version.
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 GNU
11 // Library General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16
17 #ifndef SIMGEAR_EFFECT_HXX
18 #define SIMGEAR_EFFECT_HXX 1
19
20 #include <vector>
21 #include <string>
22 #include <boost/tr1/unordered_map.hpp>
23
24 #include <boost/functional/hash.hpp>
25
26 #include <osg/Object>
27 #include <osgDB/ReaderWriter>
28
29 #include <simgear/props/props.hxx>
30 #include <simgear/scene/util/UpdateOnceCallback.hxx>
31
32 namespace osg
33 {
34 class Drawable;
35 class StateSet;
36 class RenderInfo;
37 }
38
39 namespace osgUtil
40 {
41 class CullVisitor;
42 }
43
44 namespace simgear
45 {
46 class Technique;
47 class Effect;
48
49 /**
50  * Object to be initialized at some point after an effect -- and its
51  * containing effect geode -- are hooked into the scene graph. Some
52  * things, like manipulations of the global property tree, are are
53  * only safe in the update process.
54  */
55
56 class InitializeWhenAdded
57 {
58 public:
59     InitializeWhenAdded() : _initialized(false) {};
60     virtual ~InitializeWhenAdded() {};
61     void initOnAdd(Effect* effect, SGPropertyNode* propRoot)
62     {
63         if (!_initialized) {
64             initOnAddImpl(effect, propRoot);
65             _initialized = true;
66         }
67     }
68     bool getInitialized() const { return _initialized; }
69 private:
70     virtual void initOnAddImpl(Effect* effect, SGPropertyNode* propRoot) = 0;
71     bool _initialized;
72 };
73
74 class Effect : public osg::Object
75 {
76 public:
77     META_Object(simgear,Effect)
78     Effect();
79     Effect(const Effect& rhs,
80            const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
81     osg::StateSet* getDefaultStateSet();
82     std::vector<osg::ref_ptr<Technique> > techniques;
83     SGPropertyNode_ptr root;
84     // Pointer to the parameters node, if it exists
85     SGPropertyNode_ptr parametersProp;
86     Technique* chooseTechnique(osg::RenderInfo* renderInfo);
87     virtual void resizeGLObjectBuffers(unsigned int maxSize);
88     virtual void releaseGLObjects(osg::State* state = 0) const;
89     /**
90      * Build the techniques from the effect properties.
91      */
92     bool realizeTechniques(const osgDB::ReaderWriter::Options* options = 0);
93     /**
94      * Updaters that should be derefed when the effect is
95      * deleted. Updaters arrange to be run by listening on properties
96      * or something.
97      */
98     struct Updater : public virtual SGReferenced
99     {
100         virtual ~Updater() {}
101     };
102     void addUpdater(Updater* data) { _extraData.push_back(data); }
103     // Callback that is added to the effect geode to initialize the
104     // effect.
105     friend struct InitializeCallback;
106     struct InitializeCallback : public UpdateOnceCallback
107     {
108         void doUpdate(osg::Node* node, osg::NodeVisitor* nv);
109     };
110 protected:
111     std::vector<SGSharedPtr<Updater> > _extraData;
112     ~Effect();
113     // Support for a cache of effects that inherit from this one, so
114     // Effect objects with the same parameters and techniques can be
115     // shared.
116     struct Key
117     {
118         Key() {}
119         Key(SGPropertyNode* unmerged_, const osgDB::FilePathList& paths_)
120             : unmerged(unmerged_), paths(paths_)
121         {
122         }
123         Key& operator=(const Key& rhs)
124         {
125             unmerged = rhs.unmerged;
126             paths = rhs.paths;
127             return *this;
128         }
129         SGPropertyNode_ptr unmerged;
130         osgDB::FilePathList paths;
131         struct EqualTo
132         {
133             bool operator()(const Key& lhs, const Key& rhs) const;
134         };
135     };
136     typedef std::tr1::unordered_map<Key, osg::ref_ptr<Effect>,
137                                     boost::hash<Key>, Key::EqualTo> Cache;
138     Cache* getCache()
139     {
140         if (!_cache)
141             _cache = new Cache;
142         return _cache;
143     }
144     Cache* _cache;
145     friend size_t hash_value(const Key& key);
146     friend Effect* makeEffect(SGPropertyNode* prop, bool realizeTechniques,
147                               const osgDB::ReaderWriter::Options* options);
148     bool _isRealized;
149 };
150 // Automatic support for boost hash function
151 size_t hash_value(const Effect::Key&);
152
153
154 Effect* makeEffect(const std::string& name,
155                    bool realizeTechniques,
156                    const osgDB::ReaderWriter::Options* options = 0);
157
158 Effect* makeEffect(SGPropertyNode* prop,
159                    bool realizeTechniques,
160                    const osgDB::ReaderWriter::Options* options = 0);
161
162 bool makeParametersFromStateSet(SGPropertyNode* paramRoot,
163                                 const osg::StateSet* ss);
164
165 namespace effect
166 {
167 /**
168  * The function that implements effect property tree inheritance.
169  */
170 void mergePropertyTrees(SGPropertyNode* resultNode,
171                         const SGPropertyNode* left,
172                         const SGPropertyNode* right);
173 }
174 }
175 #endif