]> git.mxchange.org Git - simgear.git/blobdiff - simgear/scene/material/Effect.hxx
Random buildings - initial commit.
[simgear.git] / simgear / scene / material / Effect.hxx
index 2a3c896ec58d2a9b8c59f5f8318245cbee902318..0a5ffe2b333008e7c86d3d479528a85576389fc8 100644 (file)
 
 #include <vector>
 #include <string>
+#include <boost/tr1/unordered_map.hpp>
+
+#include <boost/functional/hash.hpp>
 
 #include <osg/Object>
+#include <osg/observer_ptr>
 #include <osgDB/ReaderWriter>
 
 #include <simgear/props/props.hxx>
+#include <simgear/scene/util/UpdateOnceCallback.hxx>
 
 namespace osg
 {
@@ -40,6 +45,33 @@ class CullVisitor;
 namespace simgear
 {
 class Technique;
+class Effect;
+class SGReaderWriterOptions;
+
+/**
+ * Object to be initialized at some point after an effect -- and its
+ * containing effect geode -- are hooked into the scene graph. Some
+ * things, like manipulations of the global property tree, are are
+ * only safe in the update process.
+ */
+
+class InitializeWhenAdded
+{
+public:
+    InitializeWhenAdded() : _initialized(false) {};
+    virtual ~InitializeWhenAdded() {};
+    void initOnAdd(Effect* effect, SGPropertyNode* propRoot)
+    {
+        if (!_initialized) {
+            initOnAddImpl(effect, propRoot);
+            _initialized = true;
+        }
+    }
+    bool getInitialized() const { return _initialized; }
+private:
+    virtual void initOnAddImpl(Effect* effect, SGPropertyNode* propRoot) = 0;
+    bool _initialized;
+};
 
 class Effect : public osg::Object
 {
@@ -49,6 +81,31 @@ public:
     Effect(const Effect& rhs,
            const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
     osg::StateSet* getDefaultStateSet();
+
+    enum Buffer
+    {
+        DEPTH_BUFFER,
+        NORMAL_BUFFER,
+        DIFFUSE_BUFFER,
+        SPEC_EMIS_BUFFER,
+        LIGHTING_BUFFER,
+        MIDDLE_BLOOM_BUFFER,
+        BLOOM_BUFFER,
+        AO_BUFFER,
+        SHADOW_BUFFER
+    };
+
+    // Define what needs to be generated for this effect
+    enum Generator
+    {
+        NORMAL,
+        TANGENT,
+        BINORMAL
+    };
+    void setGenerator(Generator what, int where) { generator[what] = where; }
+    int getGenerator(Generator what) const;  // Returns -1 if generator should not be used
+    std::map<Generator, int> generator;  // What is generated into which attribute location
+
     std::vector<osg::ref_ptr<Technique> > techniques;
     SGPropertyNode_ptr root;
     // Pointer to the parameters node, if it exists
@@ -56,20 +113,90 @@ public:
     Technique* chooseTechnique(osg::RenderInfo* renderInfo);
     virtual void resizeGLObjectBuffers(unsigned int maxSize);
     virtual void releaseGLObjects(osg::State* state = 0) const;
-    /*
+    /**
      * Build the techniques from the effect properties.
      */
-    bool realizeTechniques(const osgDB::ReaderWriter::Options* options = 0);
-    
+    bool realizeTechniques(const SGReaderWriterOptions* options = 0);
+    /**
+     * Updaters that should be derefed when the effect is
+     * deleted. Updaters arrange to be run by listening on properties
+     * or something.
+     */
+    struct Updater : public virtual SGReferenced
+    {
+        virtual ~Updater() {}
+    };
+    void addUpdater(Updater* data) { _extraData.push_back(data); }
+    // Callback that is added to the effect geode to initialize the
+    // effect.
+    friend struct InitializeCallback;
+    struct InitializeCallback : public UpdateOnceCallback
+    {
+        void doUpdate(osg::Node* node, osg::NodeVisitor* nv);
+    };
 protected:
+    std::vector<SGSharedPtr<Updater> > _extraData;
     ~Effect();
+    // Support for a cache of effects that inherit from this one, so
+    // Effect objects with the same parameters and techniques can be
+    // shared.
+    struct Key
+    {
+        Key() {}
+        Key(SGPropertyNode* unmerged_, const osgDB::FilePathList& paths_)
+            : unmerged(unmerged_), paths(paths_)
+        {
+        }
+        Key& operator=(const Key& rhs)
+        {
+            unmerged = rhs.unmerged;
+            paths = rhs.paths;
+            return *this;
+        }
+        SGPropertyNode_ptr unmerged;
+        osgDB::FilePathList paths;
+        struct EqualTo
+        {
+            bool operator()(const Key& lhs, const Key& rhs) const;
+        };
+    };
+    typedef std::tr1::unordered_map<Key, osg::observer_ptr<Effect>,
+                                    boost::hash<Key>, Key::EqualTo> Cache;
+    Cache* getCache()
+    {
+        if (!_cache)
+            _cache = new Cache;
+        return _cache;
+    }
+    Cache* _cache;
+    friend size_t hash_value(const Key& key);
+    friend Effect* makeEffect(SGPropertyNode* prop, bool realizeTechniques,
+                              const SGReaderWriterOptions* options);
+    bool _isRealized;
 };
+// Automatic support for boost hash function
+size_t hash_value(const Effect::Key&);
+
+
 Effect* makeEffect(const std::string& name,
                    bool realizeTechniques,
-                   const osgDB::ReaderWriter::Options* options = 0);
+                   const SGReaderWriterOptions* options = 0);
 
 Effect* makeEffect(SGPropertyNode* prop,
                    bool realizeTechniques,
-                   const osgDB::ReaderWriter::Options* options = 0);
+                   const SGReaderWriterOptions* options = 0);
+
+bool makeParametersFromStateSet(SGPropertyNode* paramRoot,
+                                const osg::StateSet* ss);
+
+namespace effect
+{
+/**
+ * The function that implements effect property tree inheritance.
+ */
+void mergePropertyTrees(SGPropertyNode* resultNode,
+                        const SGPropertyNode* left,
+                        const SGPropertyNode* right);
+}
 }
 #endif