Browse Source

Polylight Changes... return a new effect on all modifiers

Shalin Shodhan 21 years ago
parent
commit
2ca64d594d
3 changed files with 206 additions and 251 deletions
  1. 0 141
      panda/src/pgraph/polylightEffect.I
  2. 188 88
      panda/src/pgraph/polylightEffect.cxx
  3. 18 22
      panda/src/pgraph/polylightEffect.h

+ 0 - 141
panda/src/pgraph/polylightEffect.I

@@ -27,115 +27,6 @@ INLINE PolylightEffect::
 PolylightEffect() {
 }
 
-
-////////////////////////////////////////////////////////////////////
-//     Function: PolylightEffect::is_enabled
-//       Access: Published
-//  Description: Returns state of the effect: enabled/disabled
-////////////////////////////////////////////////////////////////////
-INLINE bool PolylightEffect::
-is_enabled() const {
-  return _enabled;
-}
-
-
-
-////////////////////////////////////////////////////////////////////
-//     Function: PolylightEffect::enable
-//       Access: Published
-//  Description: Enables the effect
-////////////////////////////////////////////////////////////////////
-INLINE void PolylightEffect::
-enable() {
-  _enabled=true;
-}
-
-
-////////////////////////////////////////////////////////////////////
-//     Function: PolylightEffect::disable
-//       Access: Published
-//  Description: Disables the effect
-////////////////////////////////////////////////////////////////////
-INLINE void PolylightEffect::
-disable() {
-  _enabled=false;
-}
-
-
-////////////////////////////////////////////////////////////////////
-//     Function: PolylightEffect::add_light
-//       Access: Published
-//  Description: Add a PolylightNode object to this effect and give it a 
-//               unique name. Returns true if light added
-////////////////////////////////////////////////////////////////////
-INLINE bool PolylightEffect::
-add_light(const string &lightname, const NodePath &newlight) {
-  nassertr(newlight.node()->is_of_type(PolylightNode::get_class_type()) ,false);
-  nassertr(newlight.node() != (PolylightNode *)NULL,false);
-  
-  // Check if light name is unique
-  if (_lightgroup.find(lightname) != _lightgroup.end()) {
-    cerr << "Light name already exists. Please choose another name\n";
-    return false;
-  }
-    
-  // Add the light
-  pair<string,NodePath> _light_to_add(lightname, newlight);
-  _lightgroup.insert(_light_to_add);
-  return true;
-}
-
-
-////////////////////////////////////////////////////////////////////
-//     Function: PolylightEffect::remove_light
-//       Access: Published
-//  Description: Remove a light from this effect. Returns true on
-//               success.
-////////////////////////////////////////////////////////////////////
-INLINE bool PolylightEffect::
-remove_light(const string &lightname) {
-
-  // Check if light name exists
-  if (_lightgroup.find(lightname) == _lightgroup.end()) {
-    cerr << "Light name does not exist\n";
-    return false;
-  }
-
-  // Remove light
-  _lightgroup.erase(lightname);
-  return true;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PolylightEffect::remove_all
-//       Access: Published
-//  Description: Remove all the lights from this effect. Returns 
-//               true on success.
-////////////////////////////////////////////////////////////////////
-INLINE bool PolylightEffect::
-remove_all() {
-  LIGHTGROUP::const_iterator light_iter;
-  for (light_iter = _lightgroup.begin(); light_iter != _lightgroup.end(); light_iter++){
-    string lightname = light_iter->first;
-    _lightgroup.erase(lightname);
-  }
-  return true;
-}
-
-
-////////////////////////////////////////////////////////////////////
-//     Function: PolylightEffect::set_weight
-//       Access: Published
-//  Description: weight is a constant you add (generally 1 and above)
-//               to make the colorscale brighten the existing color
-////////////////////////////////////////////////////////////////////
-INLINE bool PolylightEffect::
-set_weight(float w) {
-  // nassertr(w >= 0.0 && w <= 1.0 ,false);
-  _weight = w;
-  return true;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: PolylightEffect::get_weight
 //       Access: Published
@@ -146,26 +37,6 @@ get_weight() const {
   return _weight;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: PolylightEffect::set_contrib
-//       Access: Published
-//  Description: Set the effect contribution type
-//               The effects of all the light colors are finally 
-//               divided by the number of lights. The variable
-//               _contribution_type is a string that controls how
-//               this division occurs.
-//               "proximal" : A light only contributes if the node 
-//               is inside its volume
-//               "all" : All lights added to the effect are used in
-//               division irrespective of their light volumes
-////////////////////////////////////////////////////////////////////
-INLINE bool PolylightEffect::
-set_contrib(PolylightEffect::Contrib_Type type) {
-  nassertr(type == CALL || type == CPROXIMAL,false);
-  _contribution_type = type;
-  return true;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: PolylightEffect::get_contrib
 //       Access: Published
@@ -176,18 +47,6 @@ get_contrib() const {
   return _contribution_type;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: PolylightEffect::set_effect_center
-//       Access: Published
-//  Description: Set the center point of the effect...generally 0,0,0
-//               and hence the pivot point of the model
-////////////////////////////////////////////////////////////////////
-INLINE void PolylightEffect::
-set_effect_center(LPoint3f effect_center) {
-  _effect_center = effect_center;
-}
-
-
 ////////////////////////////////////////////////////////////////////
 //     Function: PolylightEffect::get_effect_center
 //       Access: Published

+ 188 - 88
panda/src/pgraph/polylightEffect.cxx

@@ -36,13 +36,40 @@ TypeHandle PolylightEffect::_type_handle;
 CPT(RenderEffect) PolylightEffect::
 make() {
   PolylightEffect *effect = new PolylightEffect;
-  effect->enable();
-  effect->set_contrib(CPROXIMAL);
-  effect->set_weight(0.9);
+  effect->_contribution_type = CPROXIMAL;
+  effect->_weight = 0.9;
   effect->_effect_center = LPoint3f(0.0,0.0,0.0);
   return return_new(effect);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: PolylightEffect::make
+//       Access: Published, Static
+//  Description: Constructs a new PolylightEffect object.
+////////////////////////////////////////////////////////////////////
+CPT(RenderEffect) PolylightEffect::
+make(float weight, Contrib_Type contrib, LPoint3f effect_center) {
+  PolylightEffect *effect = new PolylightEffect;
+  effect->_contribution_type = contrib;
+  effect->_weight = weight;
+  effect->_effect_center = effect_center;
+  return return_new(effect);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PolylightEffect::make
+//       Access: Published, Static
+//  Description: Constructs a new PolylightEffect object.
+////////////////////////////////////////////////////////////////////
+CPT(RenderEffect) PolylightEffect::
+make(float weight, Contrib_Type contrib, LPoint3f effect_center, LIGHTGROUP lights) {
+  PolylightEffect *effect = new PolylightEffect;
+  effect->_contribution_type = contrib;
+  effect->_weight = weight;
+  effect->_effect_center = effect_center;
+  effect->_lightgroup = lights;
+  return return_new(effect);
+}
 
 ////////////////////////////////////////////////////////////////////
 //     Function: PolylightEffect::has_cull_callback
@@ -55,7 +82,7 @@ make() {
 ////////////////////////////////////////////////////////////////////
 bool PolylightEffect::
 has_cull_callback() const {
-  return is_enabled();
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -79,11 +106,9 @@ void PolylightEffect::
 cull_callback(CullTraverser *, CullTraverserData &data,
               CPT(TransformState) &node_transform,
               CPT(RenderState) &node_state) const {
-  if (is_enabled()) {
-    CPT(RenderAttrib) poly_light_attrib = do_poly_light(&data, node_transform); 
-    CPT(RenderState) poly_light_state = RenderState::make(poly_light_attrib);
-    node_state = node_state->compose(poly_light_state); 
-  }
+  CPT(RenderAttrib) poly_light_attrib = do_poly_light(&data, node_transform); 
+  CPT(RenderState) poly_light_state = RenderState::make(poly_light_attrib);
+  node_state = node_state->compose(poly_light_state); 
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -104,82 +129,78 @@ do_poly_light(const CullTraverserData *data, const TransformState *node_transfor
   r = 1.0;
   g = 1.0;
   b = 1.0;
-  if (is_enabled()) {
-    LIGHTGROUP::const_iterator light_iter; 
-    // Cycle through all the lights in this effect's lightgroup
-    for (light_iter = _lightgroup.begin(); light_iter != _lightgroup.end(); light_iter++){
-      const PolylightNode *light = DCAST(PolylightNode,light_iter->second.node()); 
-      // light holds the current PolylightNode
-      if (light->is_enabled()) { // if enabled get all the properties
-        float light_radius = light->get_radius();
-        PolylightNode::Attenuation_Type light_attenuation = light->get_attenuation();
-        float light_a0 = light->get_a0();
-        float light_a1 = light->get_a1();
-        float light_a2 = light->get_a2();
-        if (light_a0 == 0 && light_a1 == 0 && light_a2 == 0) { // To prevent division by zero
-          light_a0 = 1.0;
-        }
-        Colorf light_color;
-        if (light->is_flickering()) { // If flickering, modify color
-          light_color = light->flicker();
-        } else {
-          light_color = light->get_color_scenegraph();
-        }
-        // Calculate the distance of the node from the light
-        //dist = light_iter->second->get_distance(data->_node_path.get_node_path());
-        const NodePath lightnp = light_iter->second;
-        LPoint3f point = data->_node_path.get_node_path().get_relative_point(lightnp,
-          light->get_pos());
-        dist = (point - _effect_center).length();
-
-        if (dist < light_radius) { // If node is in range of this light
-          if (light_attenuation == PolylightNode::ALINEAR) {
-            light_scale = (light_radius - dist)/light_radius;
-          } else if (light_attenuation == PolylightNode::AQUADRATIC) {
-            fd = 1.0 / (light_a0 + light_a1 * dist + light_a2 * dist * dist);
-            if (fd < 1.0) {
-              light_scale = fd;
-            } else {
-              light_scale = 1.0;
-            }
-         } else {
-             light_scale = 1.0;
-         }
-         // Keep accumulating each lights contribution... we divide by 
-         // number of lights later.
-           Rcollect += light_color[0] * light_scale;
-           Gcollect += light_color[1] * light_scale;
-           Bcollect += light_color[2] * light_scale;
-           num_lights++;
-        } // if dist< radius
-      } // if light is enabled
-    } // for all lights
-  
-
-    if ( _contribution_type == CALL) {
-      // Sometimes to prevent snapping of color at light volume boundaries
-      // just divide total contribution by all the lights in the effect
-      // whether or not they contribute color
-      num_lights = _lightgroup.size();
-    }
-
-    if (num_lights == 0) {
-      no_lights_closeby = true;
-      num_lights = 1;
-    }
-    Rcollect /= num_lights;
-    Gcollect /= num_lights;
-    Bcollect /= num_lights;
-
-    if (!no_lights_closeby) {
-      //r = 1.0 + ((1.0 - _weight) + Rcollect * _weight);
-      //g = 1.0 + ((1.0 - _weight) + Gcollect * _weight);
-      //b = 1.0 + ((1.0 - _weight) + Bcollect * _weight);
-      r = _weight + Rcollect;
-      g = _weight + Gcollect;
-      b = _weight + Bcollect;
-    }
+  LIGHTGROUP::const_iterator light_iter; 
+  // Cycle through all the lights in this effect's lightgroup
+  for (light_iter = _lightgroup.begin(); light_iter != _lightgroup.end(); light_iter++){
+    const PolylightNode *light = DCAST(PolylightNode, (*light_iter).node()); 
+    // light holds the current PolylightNode
+    if (light->is_enabled()) { // if enabled get all the properties
+      float light_radius = light->get_radius();
+      PolylightNode::Attenuation_Type light_attenuation = light->get_attenuation();
+      float light_a0 = light->get_a0();
+      float light_a1 = light->get_a1();
+      float light_a2 = light->get_a2();
+      if (light_a0 == 0 && light_a1 == 0 && light_a2 == 0) { // To prevent division by zero
+        light_a0 = 1.0;
+      }
+      Colorf light_color;
+      if (light->is_flickering()) { // If flickering, modify color
+        light_color = light->flicker();
+      } else {
+        light_color = light->get_color_scenegraph();
+      }
+      // Calculate the distance of the node from the light
+      //dist = light_iter->second->get_distance(data->_node_path.get_node_path());
+      const NodePath lightnp = *light_iter;
+      LPoint3f point = data->_node_path.get_node_path().get_relative_point(lightnp,
+        light->get_pos());
+      dist = (point - _effect_center).length();
+       if (dist < light_radius) { // If node is in range of this light
+        if (light_attenuation == PolylightNode::ALINEAR) {
+          light_scale = (light_radius - dist)/light_radius;
+        } else if (light_attenuation == PolylightNode::AQUADRATIC) {
+          fd = 1.0 / (light_a0 + light_a1 * dist + light_a2 * dist * dist);
+          if (fd < 1.0) {
+            light_scale = fd;
+          } else {
+            light_scale = 1.0;
+          }
+       } else {
+           light_scale = 1.0;
+       }
+       // Keep accumulating each lights contribution... we divide by 
+       // number of lights later.
+         Rcollect += light_color[0] * light_scale;
+         Gcollect += light_color[1] * light_scale;
+         Bcollect += light_color[2] * light_scale;
+         num_lights++;
+      } // if dist< radius
+    } // if light is enabled
+  } // for all lights
+
+
+  if ( _contribution_type == CALL) {
+    // Sometimes to prevent snapping of color at light volume boundaries
+    // just divide total contribution by all the lights in the effect
+    // whether or not they contribute color
+    num_lights = _lightgroup.size();
   }
+  if (num_lights == 0) {
+    no_lights_closeby = true;
+    num_lights = 1;
+  }
+  Rcollect /= num_lights;
+  Gcollect /= num_lights;
+  Bcollect /= num_lights;
+  if (!no_lights_closeby) {
+    //r = 1.0 + ((1.0 - _weight) + Rcollect * _weight);
+    //g = 1.0 + ((1.0 - _weight) + Gcollect * _weight);
+    //b = 1.0 + ((1.0 - _weight) + Bcollect * _weight);
+    r = _weight + Rcollect;
+    g = _weight + Gcollect;
+    b = _weight + Bcollect;
+  }
+
   return ColorScaleAttrib::make(LVecBase4f(r, g, b, 1.0));
 }
 
@@ -204,10 +225,6 @@ compare_to_impl(const RenderEffect *other) const {
   const PolylightEffect *ta;
   DCAST_INTO_R(ta, other, 0);
 
-  if (_enabled != ta->_enabled) {
-    return _enabled ? 1 : -1;
-  }
-
   if (_contribution_type != ta->_contribution_type) {
     return _contribution_type < ta->_contribution_type ? -1 : 1;
   }
@@ -223,3 +240,86 @@ compare_to_impl(const RenderEffect *other) const {
   return 0;
 }
 
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: PolylightEffect::add_light
+//       Access: Published
+//  Description: Add a PolylightNode object to this effect and return
+//               a new effect
+////////////////////////////////////////////////////////////////////
+CPT(RenderEffect) PolylightEffect::
+add_light(const NodePath &newlight) {
+  _lightgroup.push_back(newlight);
+  return make(_weight,_contribution_type, _effect_center, 
+  _lightgroup);
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: PolylightEffect::remove_light
+//       Access: Published
+//  Description: Remove a light from this effect. Return the new updated
+//               effect
+////////////////////////////////////////////////////////////////////
+CPT(RenderEffect) PolylightEffect::
+remove_light(const NodePath &newlight) {
+
+  LIGHTGROUP::iterator light_iter;
+  light_iter = find(_lightgroup.begin(),_lightgroup.end(), newlight); 
+  if(light_iter == _lightgroup.end()) {
+    cerr << "Light Not Found!\n";
+  } else {
+    // Remove light
+    _lightgroup.erase(light_iter);
+  }
+  return make(_weight, _contribution_type, _effect_center, 
+  _lightgroup);
+ 
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PolylightEffect::set_weight
+//       Access: Published
+//  Description: Set weight and return a new effect... the reason
+//               this couldnt be done through make was because
+//               that would return a new effect without the 
+//               lightgroup which is static and cant be accessed
+//               Here, we just pass that to the make
+////////////////////////////////////////////////////////////////////
+CPT(RenderEffect) PolylightEffect::
+set_weight(float w) {
+  return make(w,_contribution_type, _effect_center, 
+  _lightgroup);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PolylightEffect::set_contrib
+//       Access: Published
+//  Description: Set Contrib Type and return a new effect... the reason
+//               this couldnt be done through make was because
+//               that would return a new effect without the 
+//               lightgroup which is static and cant be accessed
+//               Here, we just pass that to the make
+////////////////////////////////////////////////////////////////////
+CPT(RenderEffect) PolylightEffect::
+set_contrib(Contrib_Type ct) {
+  return make(_weight, ct, _effect_center, 
+  _lightgroup);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PolylightEffect::set_effect_center
+//       Access: Published
+//  Description: Set weight and return a new effect... the reason
+//               this couldnt be done through make was because
+//               that would return a new effect without the 
+//               lightgroup which is static and cant be accessed
+//               Here, we just pass that to the make
+////////////////////////////////////////////////////////////////////
+CPT(RenderEffect) PolylightEffect::
+set_effect_center(LPoint3f ec) {
+  return make(_weight,_contribution_type, ec, 
+  _lightgroup);
+}
+

+ 18 - 22
panda/src/pgraph/polylightEffect.h

@@ -34,15 +34,13 @@
 //       Class : PolylightEffect
 // Description : A PolylightEffect can be used on a node to define a
 //               LightGroup  for that node. A LightGroup contains 
-//               Polylights which are essentially nodes that add 
+//               PolylightNodes which are essentially nodes that add 
 //               color to the polygons of a model based on distance.
 //               PolylightNode is a cheap way to get lighting effects
 //               specially for night scenes
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA PolylightEffect : public RenderEffect {
-private:
-  INLINE PolylightEffect();
-  
+
 
 PUBLISHED:
   enum Contrib_Type {
@@ -50,18 +48,25 @@ PUBLISHED:
     CALL,
   };
 
+private:
+  INLINE PolylightEffect();
+  Contrib_Type _contribution_type;
+  float _weight;
+  typedef pvector< NodePath > LIGHTGROUP;
+  LIGHTGROUP _lightgroup;
+  LPoint3f _effect_center;
+
+PUBLISHED:
   static CPT(RenderEffect) make();
-  INLINE void enable();
-  INLINE void disable();
-  INLINE bool add_light(const string &lightname, const NodePath &newlight);
-  INLINE bool remove_light(const string &lightname);
-  INLINE bool remove_all();
-  INLINE bool set_weight(float w);
+  static CPT(RenderEffect) make(float weight, Contrib_Type contrib, LPoint3f effect_center);
+  static CPT(RenderEffect) make(float weight, Contrib_Type contrib, LPoint3f effect_center, LIGHTGROUP lights);
+  CPT(RenderEffect) add_light(const NodePath &newlight);
+  CPT(RenderEffect) remove_light(const NodePath &newlight);
+  CPT(RenderEffect) set_weight(float w);
+  CPT(RenderEffect) set_contrib(Contrib_Type c);
+  CPT(RenderEffect) set_effect_center(LPoint3f ec);
   INLINE float get_weight() const;
-  INLINE bool set_contrib(Contrib_Type type);  
   INLINE Contrib_Type get_contrib() const;
-  INLINE bool is_enabled()const;
-  INLINE void set_effect_center(LPoint3f effect_center);
   INLINE LPoint3f get_effect_center()const;
 
 public:
@@ -75,15 +80,6 @@ public:
 protected:
   virtual int compare_to_impl(const RenderEffect *other) const;
 
-private:
-  bool _enabled;
-  Contrib_Type _contribution_type;
-  float _weight;
-  typedef pmap<string, NodePath> LIGHTGROUP;
-  LIGHTGROUP _lightgroup;
-  LPoint3f _effect_center;
-  
-
 public:
   static TypeHandle get_class_type() {
     return _type_handle;