From 2ca64d594deb22b6484b3355a3446c0b68955ec3 Mon Sep 17 00:00:00 2001 From: Shalin Shodhan Date: Fri, 30 Jul 2004 21:04:11 +0000 Subject: [PATCH] Polylight Changes... return a new effect on all modifiers --- panda/src/pgraph/polylightEffect.I | 141 -------------- panda/src/pgraph/polylightEffect.cxx | 272 ++++++++++++++++++--------- panda/src/pgraph/polylightEffect.h | 40 ++-- 3 files changed, 204 insertions(+), 249 deletions(-) diff --git a/panda/src/pgraph/polylightEffect.I b/panda/src/pgraph/polylightEffect.I index 7840f97e43..e213415f18 100755 --- a/panda/src/pgraph/polylightEffect.I +++ b/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 _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 diff --git a/panda/src/pgraph/polylightEffect.cxx b/panda/src/pgraph/polylightEffect.cxx index f9bea200e9..157307b8a3 100755 --- a/panda/src/pgraph/polylightEffect.cxx +++ b/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(); + 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 (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; - } + 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); +} + diff --git a/panda/src/pgraph/polylightEffect.h b/panda/src/pgraph/polylightEffect.h index 9361908a74..4d4cb89166 100755 --- a/panda/src/pgraph/polylightEffect.h +++ b/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 LIGHTGROUP; - LIGHTGROUP _lightgroup; - LPoint3f _effect_center; - - public: static TypeHandle get_class_type() { return _type_handle;