Просмотр исходного кода

Added RenderState::clearParameter method to allow existing material parameter values/bindings to be cleared.
Added Terrain::Listener interface with a materialUpdated to allow customization of Terrain/TerrainPatch materials.

Steve Grenier 13 лет назад
Родитель
Сommit
6e69d767bd

+ 14 - 0
gameplay/src/RenderState.cpp

@@ -77,6 +77,20 @@ MaterialParameter* RenderState::getParameter(const char* name) const
     return param;
 }
 
+void RenderState::clearParameter(const char* name)
+{
+    for (size_t i = 0, count = _parameters.size(); i < count; ++i)
+    {
+        MaterialParameter* p = _parameters[i];
+        if (p->_name == name)
+        {
+            _parameters.erase(_parameters.begin() + i);
+            SAFE_RELEASE(p);
+            break;
+        }
+    }
+}
+
 /**
  * @script{ignore}
  */

+ 13 - 0
gameplay/src/RenderState.h

@@ -306,12 +306,25 @@ public:
      * The returned MaterialParameter can be used to set values for the specified
      * parameter name.
      *
+     * Note that this method causes a new MaterialParameter to be created if one
+     * does not already exist for the given parameter name.
+     *
      * @param name Material parameter (uniform) name.
      * 
      * @return A MaterialParameter for the specified name.
      */
     MaterialParameter* getParameter(const char* name) const;
 
+    /**
+     * Clears the MaterialParameter with the given name.
+     *
+     * If a material parameter exists for the given name, it is destroyed and
+     * removed from this RenderState.
+     *
+     * @param name Material parameter (uniform) name.
+     */
+    void clearParameter(const char* name);
+
     /**
      * Sets a material parameter auto-binding.
      *

+ 33 - 0
gameplay/src/Terrain.cpp

@@ -38,6 +38,8 @@ Terrain::Terrain() :
 
 Terrain::~Terrain()
 {
+    _listeners.clear();
+
     for (size_t i = 0, count = _patches.size(); i < count; ++i)
     {
         SAFE_DELETE(_patches[i]);
@@ -512,6 +514,37 @@ void Terrain::transformChanged(Transform* transform, long cookie)
     _dirtyFlags |= TERRAIN_DIRTY_WORLD_MATRIX | TERRAIN_DIRTY_INV_WORLD_MATRIX | TERRAIN_DIRTY_NORMAL_MATRIX;
 }
 
+void Terrain::addListener(Terrain::Listener* listener)
+{
+    _listeners.push_back(listener);
+
+    // Fire initial events in case this listener may have missed them
+    for (size_t i = 0, patchCount = _patches.size(); i < patchCount; ++i)
+    {
+        TerrainPatch* patch = _patches[i];
+        for (size_t j = 0, levelCount = patch->_levels.size(); j < levelCount; ++j)
+        {
+            TerrainPatch::Level* level = patch->_levels[j];
+            Material* material = level->model ? level->model->getMaterial() : NULL;
+            if (material)
+            {
+                // Fire materialUpdated event for materials that are already active
+                for (size_t k = 0, lcount = _listeners.size(); k < lcount; ++k)
+                {
+                    _listeners[k]->materialUpdated(this, material);
+                }
+            }
+        }
+    }
+}
+
+void Terrain::removeListener(Terrain::Listener* listener)
+{
+    std::vector<Terrain::Listener*>::iterator itr = std::find(_listeners.begin(), _listeners.end(), listener);
+    if (itr != _listeners.end())
+        _listeners.erase(itr);
+}
+
 const Matrix& Terrain::getWorldMatrix() const
 {
     if (_dirtyFlags & TERRAIN_DIRTY_WORLD_MATRIX)

+ 72 - 25
gameplay/src/Terrain.h

@@ -114,6 +114,28 @@ public:
          LEVEL_OF_DETAIL = 8
     };
 
+    /**
+     * Interface for various terrain-specific events that can be handled.
+     */
+    class Listener
+    {
+    public:
+
+        virtual ~Listener() { }
+
+        /**
+         * Fired when a material is updated for the terrain or a patch within it.
+         *
+         * This method can be handled to override material parameters for the terrain.
+         * Note that this method will usually be fired several times since there are
+         * normally separate materials defined per patch.
+         *
+         * @param terrain The terrain firing the event.
+         * @param material The new material.
+         */
+        virtual void materialUpdated(Terrain* terrain, Material* material) = 0;
+    };
+
     /**
      * Loads a Terrain from the given properties file.
      *
@@ -301,67 +323,91 @@ public:
      */
     void transformChanged(Transform* transform, long cookie);
 
-private:
+    /**
+     * Adds a listener to this terrain.
+     *
+     * @param listener Listener to start receiving terrain events.
+     */
+    void addListener(Terrain::Listener* listener);
 
     /**
-     * Constructor.
+     * Removes a listener from this terrain.
+     *
+     * @param listener Listener to stop receiving terrain events.
      */
-    Terrain();
+    void removeListener(Terrain::Listener* listener);
 
     /**
-     * Hidden copy constructor.
+     * Returns the world matrix of the terrain, factoring in terrain local scaling.
+     *
+     * @return The world matrix for the terrain.
      */
-    Terrain(const Terrain&);
+    const Matrix& getWorldMatrix() const;
 
     /**
-     * Hidden copy assignment operator.
+     * Returns the terrain's inverse world matrix.
+     *
+     * @return The inverse world matrix for the terrain.
      */
-    Terrain& operator=(const Terrain&);
+    const Matrix& getInverseWorldMatrix() const;
 
     /**
-     * Destructor.
+     * Returns a matrix to be used for transforming normal vectors for the terrain.
+     *
+     * @return The matrix used for normal vector transformation for the terrain.
      */
-    ~Terrain();
+    const Matrix& getNormalMatrix() const;
 
     /**
-     * Internal method for creating terrain.
+     * Returns the world view matrix for the terrain, factoring in terrain local scaling.
+     *
+     * @return The world-view matrix for the terrain.
      */
-    static Terrain* create(HeightField* heightfield, const Vector3& scale, unsigned int patchSize, unsigned int detailLevels, float skirtScale, const char* normalMapPath, Properties* properties);
+    const Matrix& getWorldViewMatrix() const;
 
     /**
-     * Internal method for creating terrain.
+     * Returns the world view projection matrix for the terrain, factoring in terrain local scaling.
+     *
+     * @return The world-view-projection matrix for the terrain.
      */
-    static Terrain* create(const char* path, Properties* properties);
+    const Matrix& getWorldViewProjectionMatrix() const;
+
+private:
 
     /**
-     * Sets the node that the terrain is attached to.
+     * Constructor.
      */
-    void setNode(Node* node);
+    Terrain();
 
     /**
-     * Returns the world matrix of the terrain, factoring in terrain local scaling.
+     * Hidden copy constructor.
      */
-    const Matrix& getWorldMatrix() const;
+    Terrain(const Terrain&);
 
     /**
-     * Returns the terrain's inverse world matrix.
+     * Hidden copy assignment operator.
      */
-    const Matrix& getInverseWorldMatrix() const;
+    Terrain& operator=(const Terrain&);
 
     /**
-     * Returns a matrix to be used for transforming normal vectors for the terrain.
+     * Destructor.
      */
-    const Matrix& getNormalMatrix() const;
+    ~Terrain();
 
     /**
-     * Returns the world view matrix for the terrain, factoring in terrain local scaling.
+     * Internal method for creating terrain.
      */
-    const Matrix& getWorldViewMatrix() const;
+    static Terrain* create(HeightField* heightfield, const Vector3& scale, unsigned int patchSize, unsigned int detailLevels, float skirtScale, const char* normalMapPath, Properties* properties);
 
     /**
-     * Returns the world view projection matrix for the terrain, factoring in terrain local scaling.
+     * Internal method for creating terrain.
      */
-    const Matrix& getWorldViewProjectionMatrix() const;
+    static Terrain* create(const char* path, Properties* properties);
+
+    /**
+     * Sets the node that the terrain is attached to.
+     */
+    void setNode(Node* node);
 
     HeightField* _heightfield;
     Node* _node;
@@ -374,6 +420,7 @@ private:
     mutable Matrix _normalMatrix;
     mutable unsigned int _dirtyFlags;
     BoundingBox _boundingBox;
+    std::vector<Terrain::Listener*> _listeners;
 };
 
 }

+ 6 - 0
gameplay/src/TerrainPatch.cpp

@@ -498,6 +498,12 @@ bool TerrainPatch::updateMaterial()
             material->getParameter("u_column")->setValue((float)_column);
         }
 
+        // Fire terrain listeners
+        for (size_t j = 0, lcount = _terrain->_listeners.size(); j < lcount; ++j)
+        {
+            _terrain->_listeners[j]->materialUpdated(_terrain, material);
+        }
+
         // Set material on this lod level
         _levels[i]->model->setMaterial(material);