From 88b9702137b7abb3cc44ecebd3d78ddb5204dd37 Mon Sep 17 00:00:00 2001 From: Shalin Shodhan Date: Mon, 14 Jun 2004 18:48:27 +0000 Subject: [PATCH] Polylight API --- panda/src/pgraph/polylightEffect.I | 177 ++++++++++ panda/src/pgraph/polylightEffect.cxx | 166 +++++++++ panda/src/pgraph/polylightEffect.h | 99 ++++++ panda/src/pgraph/polylightNode.I | 490 +++++++++++++++++++++++++++ panda/src/pgraph/polylightNode.cxx | 298 ++++++++++++++++ panda/src/pgraph/polylightNode.h | 150 ++++++++ 6 files changed, 1380 insertions(+) create mode 100755 panda/src/pgraph/polylightEffect.I create mode 100755 panda/src/pgraph/polylightEffect.cxx create mode 100755 panda/src/pgraph/polylightEffect.h create mode 100755 panda/src/pgraph/polylightNode.I create mode 100755 panda/src/pgraph/polylightNode.cxx create mode 100755 panda/src/pgraph/polylightNode.h diff --git a/panda/src/pgraph/polylightEffect.I b/panda/src/pgraph/polylightEffect.I new file mode 100755 index 0000000000..86a11bffc9 --- /dev/null +++ b/panda/src/pgraph/polylightEffect.I @@ -0,0 +1,177 @@ +// Filename: polylightEffect.I +// Created by: sshodhan (02Jun04) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: PolylightEffect::Constructor +// Access: Private +// Description: Use PolylightEffect::make() to construct a new +// PolylightEffect object. +//////////////////////////////////////////////////////////////////// +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(string lightname,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(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: Set a weight between 0 and 1 for the light effect +// This affects how much original color and how much +// light color are applied to the node +//////////////////////////////////////////////////////////////////// +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 +// Description: Get the weight value +//////////////////////////////////////////////////////////////////// +INLINE float PolylightEffect:: +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(string type) { + nassertr(type == "all" || type == "proximal",false); + _contribution_type = type; + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightEffect::get_contrib +// Access: Published +// Description: Returns a string value "all"/"proximal" +//////////////////////////////////////////////////////////////////// +INLINE string PolylightEffect:: +get_contrib() const { + return _contribution_type; +} \ No newline at end of file diff --git a/panda/src/pgraph/polylightEffect.cxx b/panda/src/pgraph/polylightEffect.cxx new file mode 100755 index 0000000000..7fb1896bee --- /dev/null +++ b/panda/src/pgraph/polylightEffect.cxx @@ -0,0 +1,166 @@ +// Filename: polylightEffect.cxx +// Created by: sshodhan (02Jun04) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "polylightEffect.h" +#include "polylightNode.h" +#include "config_pgraph.h" +#include "nodePath.h" +#include "pmap.h" +#include +TypeHandle PolylightEffect::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: PolylightEffect::make +// Access: Published, Static +// Description: Constructs a new PolylightEffect object. +//////////////////////////////////////////////////////////////////// +CPT(RenderEffect) PolylightEffect:: +make(string contribution_type,float weight) { + PolylightEffect *effect = new PolylightEffect; + effect->enable(); + effect->set_contrib(contribution_type); + effect->set_weight(weight); + return return_new(effect); +} +//////////////////////////////////////////////////////////////////// +// Function: PolylightEffect::do_poly_light +// Access: Public +// Description: Gets the node's position and based on distance from +// lights in the lightgroup calculates the color to be modulated in +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) PolylightEffect:: +do_poly_light(const CullTraverserData *data, const TransformState *node_transform) const { + float r,g,b; // To hold the color calculation + float dist; // To calculate the distance of each light from the node + float light_scale; // Variable to calculate attenuation + float fd; // Variable for quadratic attenuation + float Rcollect=0.0,Gcollect=0.0,Bcollect=0.0; // Color variables + int num_lights=0; // Keep track of number of lights for division + r = 0.0; + g = 0.0; + b = 0.0; + 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(); + string 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(); + } + + // Calculate the distance of the node from the light + dist = light_iter->second->get_distance(data->_node_path.get_node_path()); + + if(dist < light_radius) { // If node is in range of this light + if(light_attenuation == "linear") { + light_scale = (light_radius - dist)/light_radius; + } + else if(light_attenuation == "quadratic") { + fd = 1.0 / (light_a0 + light_a1 * dist + light_a2 * dist * dist); + if(fd<1.0) { + light_scale=fd; + } + 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 == "all") { + // 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) { + num_lights = 1; + } + Rcollect /= num_lights; + Gcollect /= num_lights; + Bcollect /= num_lights; + + r = (1.0 - _weight) + Rcollect * _weight; + g = (1.0 - _weight) + Gcollect * _weight; + b = (1.0 - _weight) + Bcollect * _weight; + + return ColorScaleAttrib::make(LVecBase4f(r,g,b,1.0)); +} + + +//////////////////////////////////////////////////////////////////// +// Function: PolylightEffect::compare_to_impl +// Access: Protected, Virtual +// Description: Intended to be overridden by derived PolylightEffect +// types to return a unique number indicating whether +// this PolylightEffect is equivalent to the other one. +// +// This should return 0 if the two PolylightEffect objects +// are equivalent, a number less than zero if this one +// should be sorted before the other one, and a number +// greater than zero otherwise. +// +// This will only be called with two PolylightEffect +// objects whose get_type() functions return the same. +//////////////////////////////////////////////////////////////////// +int PolylightEffect:: +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; + } + + if (_weight != ta->_weight) { + return _weight < ta->_weight ? -1 :1; + } + + if (_lightgroup != ta->_lightgroup) { + return _lightgroup < ta->_lightgroup ? -1 : 1; + } + + return 0; +} + diff --git a/panda/src/pgraph/polylightEffect.h b/panda/src/pgraph/polylightEffect.h new file mode 100755 index 0000000000..df229caa8d --- /dev/null +++ b/panda/src/pgraph/polylightEffect.h @@ -0,0 +1,99 @@ +// Filename: polylightEffect.h +// Created by: sshodhan (01Jun04) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef POLYLIGHTEFFECT_H +#define POLYLIGHTEFFECT_H + +#include "pandabase.h" + + +#include "renderEffect.h" +#include "luse.h" +#include "nodePath.h" +#include "polylightNode.h" +#include "pmap.h" +#include "notify.h" + + +//////////////////////////////////////////////////////////////////// +// 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 +// 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: + + static CPT(RenderEffect) make(string contribution_type= "proximal", float weight=0.9); + INLINE void enable(); + INLINE void disable(); + INLINE bool add_light(string lightname, NodePath *newlight); + INLINE bool remove_light(string lightname); + INLINE bool remove_all(); + INLINE bool set_weight(float w); + INLINE float get_weight() const; + INLINE bool set_contrib(string type); + INLINE string get_contrib() const; + INLINE bool is_enabled()const; + +public: + CPT(RenderAttrib) do_poly_light(const CullTraverserData *data, const TransformState *node_transform) const; + + +protected: + virtual int compare_to_impl(const RenderEffect *other) const; + +private: + bool _enabled; + string _contribution_type; + float _weight; + typedef pmap LIGHTGROUP; + LIGHTGROUP _lightgroup; + + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + RenderEffect::init_type(); + register_type(_type_handle, "PolylightEffect", + RenderEffect::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "polylightEffect.I" + +#endif + + + diff --git a/panda/src/pgraph/polylightNode.I b/panda/src/pgraph/polylightNode.I new file mode 100755 index 0000000000..0ea8b3f033 --- /dev/null +++ b/panda/src/pgraph/polylightNode.I @@ -0,0 +1,490 @@ +// Filename: PolylightNodeEffect.I +// Created by: sshodhan (02Jun04) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::operator == +// Access: Published +// Description: Returns true if the two lights are equivalent +// that is, all their properties are same +//////////////////////////////////////////////////////////////////// +INLINE bool PolylightNode:: +operator == (const PolylightNode &other) const { + return (compare_to(other) == 0); +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::operator != +// Access: Published +// Description: Returns true if the two lights are not equivalent. +//////////////////////////////////////////////////////////////////// +INLINE bool PolylightNode:: +operator != (const PolylightNode &other) const { + return (compare_to(other) != 0); +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::operator < +// Access: Published +// Description: Returns true if this PolylightNode sorts before the other +// one, false otherwise. The sorting order of two +// nonequivalent PolylightNodes is consistent but undefined, +// and is useful only for storing PolylightNodes in a sorted +// container like an STL set. +//////////////////////////////////////////////////////////////////// +INLINE bool PolylightNode:: +operator < (const PolylightNode &other) const { + return (compare_to(other) < 0); +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::is_enabled +// Access: Published +// Description: Is this light is enabled/disabled? +//////////////////////////////////////////////////////////////////// +INLINE bool PolylightNode::is_enabled() const { + return _enabled; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::enable +// Access: Published +// Description: Enable this light +//////////////////////////////////////////////////////////////////// +INLINE void PolylightNode::enable(){ + _enabled=true; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::disable +// Access: Published +// Description: Disable this light +//////////////////////////////////////////////////////////////////// +INLINE void PolylightNode::disable(){ + _enabled=false; +} + + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::set_pos +// Access: Published +// Description: Set this light's position +//////////////////////////////////////////////////////////////////// +INLINE void PolylightNode::set_pos(float x, float y, float z){ + LVecBase3f position; + position[0]=x; + position[1]=y; + position[2]=z; + PandaNode::set_transform(get_transform()->set_pos(position)); + PandaNode::reset_prev_transform(); +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::get_pos +// Access: Published +// Description: Returns position as a LPoint3f +//////////////////////////////////////////////////////////////////// +INLINE LVecBase3f PolylightNode::get_pos() const { + return PandaNode::get_transform()->get_pos(); +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::set_radius +// Access: Published +// Description: Set radius of the spherical light volume +//////////////////////////////////////////////////////////////////// +INLINE void PolylightNode::set_radius(float r){ + _radius=r; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::get_radius +// Access: Published +// Description: Get radius of the spherical light volume +//////////////////////////////////////////////////////////////////// +INLINE float PolylightNode::get_radius() const { + return _radius; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::set_attenuation +// Access: Published +// Description: Set "linear" or "quadratic" attenuation +//////////////////////////////////////////////////////////////////// +INLINE bool PolylightNode::set_attenuation(string type){ + nassertr(type == "linear" || type == "quadratic",false); + + _attenuation_type=type; + return true; + +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::get_attenuation +// Access: Published +// Description: Get "linear" or "quadratic" attenuation type +//////////////////////////////////////////////////////////////////// +INLINE string PolylightNode::get_attenuation() const { + return _attenuation_type; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::set_a0 +// Access: Published +// Description: Set the quadratic attenuation factor a0 +// fd = 1 / ( a0 + a1*distance + a2*distance*distance) +//////////////////////////////////////////////////////////////////// +INLINE void PolylightNode::set_a0(float a0){ + _a0=a0; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::set_a1 +// Access: Published +// Description: Set the quadratic attenuation factor a1 +// fd = 1 / ( a0 + a1*distance + a2*distance*distance) +//////////////////////////////////////////////////////////////////// +INLINE void PolylightNode::set_a1(float a1){ + _a1=a1; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::set_a2 +// Access: Published +// Description: Set the quadratic attenuation factor a2 +// fd = 1 / ( a0 + a1*distance + a2*distance*distance) +//////////////////////////////////////////////////////////////////// +INLINE void PolylightNode::set_a2(float a2){ + _a2=a2; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::get_a0 +// Access: Published +// Description: Get the quadratic attenuation factor a0 +// fd = 1 / ( a0 + a1*distance + a2*distance*distance) +//////////////////////////////////////////////////////////////////// +INLINE float PolylightNode::get_a0() const { + return _a0; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::get_a1 +// Access: Published +// Description: Get the quadratic attenuation factor a1 +// fd = 1 / ( a0 + a1*distance + a2*distance*distance) +//////////////////////////////////////////////////////////////////// +INLINE float PolylightNode::get_a1() const { + return _a1; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::get_a2 +// Access: Published +// Description: Get the quadratic attenuation factor a2 +// fd = 1 / ( a0 + a1*distance + a2*distance*distance) +//////////////////////////////////////////////////////////////////// +INLINE float PolylightNode::get_a2() const { + return _a2; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::flicker_on +// Access: Published +// Description: Set flickering to true so at every loop this light's +// color is varied based on flicker_type +//////////////////////////////////////////////////////////////////// +INLINE void PolylightNode::flicker_on(){ + _flickering=true; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::flicker_off +// Access: Published +// Description: Turn flickering off +//////////////////////////////////////////////////////////////////// +INLINE void PolylightNode::flicker_off(){ + _flickering=false; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::is_flickering +// Access: Published +// Description: Check is this light is flickering +//////////////////////////////////////////////////////////////////// +INLINE bool PolylightNode::is_flickering() const { + return _flickering; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::set_flicker_type +// Access: Published +// Description: Flicker type can be "random" or "sin" +// At a later point there might be a "custom" +// Custom flicker will be a set of fix points recorded +// by animating the light's intensity +//////////////////////////////////////////////////////////////////// +INLINE bool PolylightNode::set_flicker_type(string type){ + nassertr(type == "random" || type == "sin",false); + + + _flicker_type=type; + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::get_flicker_type +// Access: Published +// Description: Returns "random" or "sin" +//////////////////////////////////////////////////////////////////// +INLINE string PolylightNode::get_flicker_type() const { + return _flicker_type; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::set_offset +// Access: Published +// Description: Set the offset value for the random and sin +// flicker variations... used to tweak the flicker +// This value is added to the variation +//////////////////////////////////////////////////////////////////// +INLINE void PolylightNode::set_offset(float offset){ + _offset=offset; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::get_offset +// Access: Published +// Description: Get the offset value for the random and sin +// flicker variations +//////////////////////////////////////////////////////////////////// +INLINE float PolylightNode::get_offset() const { + return _offset; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::set_scale +// Access: Published +// Description: Set the scale value for the random and sin +// flicker variations... used to tweak the flicker +// This value is multiplied with the variation +//////////////////////////////////////////////////////////////////// +INLINE void PolylightNode::set_scale(float scale){ + _scale=scale; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::get_scale +// Access: Published +// Description: Get the scale value for the random and sin +// flicker variations +//////////////////////////////////////////////////////////////////// +INLINE float PolylightNode::get_scale() const { + return _scale; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::set_step_size +// Access: Published +// Description: Set the step size for the sin function in flicker +// This is the increment size for the value supplied +// to the sin function +//////////////////////////////////////////////////////////////////// +INLINE void PolylightNode::set_step_size(float step){ + _step_size=step; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::get_step_size +// Access: Published +// Description: Get the step size for the sin function in flicker +// This is the increment size for the value supplied +// to the sin function +//////////////////////////////////////////////////////////////////// +INLINE float PolylightNode::get_step_size() const { + return _step_size; +} + + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::set_color +// Access: Published +// Description: Set the light's color... 3 floats between 0 and 1 +//////////////////////////////////////////////////////////////////// +INLINE void PolylightNode::set_color(float r, float g, float b) { + Colorf color; + color[0] = r; + color[1] = g; + color[2] = b; + color[3] = 1.0; + PandaNode::set_attrib(ColorAttrib::make_flat(color)); +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::get_color +// Access: Published +// Description: Returns the light's color as Colorf +//////////////////////////////////////////////////////////////////// +INLINE Colorf PolylightNode::get_color() const { + + const RenderAttrib *attrib = + PandaNode::get_attrib(ColorAttrib::get_class_type()); + if (attrib != (const RenderAttrib *)NULL) { + const ColorAttrib *ca = DCAST(ColorAttrib, attrib); + if (ca->get_color_type() == ColorAttrib::T_flat) { + return ca->get_color(); + } + } + + return Colorf(1.0f, 1.0f, 1.0f, 1.0f); + +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::set_x +// Access: Published +// Description: Set light's x position +//////////////////////////////////////////////////////////////////// +INLINE void PolylightNode::set_x(float x) { + LPoint3f pos = get_pos(); + pos[0] = x; + set_pos(pos[0],pos[1],pos[2]); +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::set_y +// Access: Published +// Description: Set light's y position +//////////////////////////////////////////////////////////////////// +INLINE void PolylightNode::set_y(float y) { + LPoint3f pos = get_pos(); + pos[1] = y; + set_pos(pos[0],pos[1],pos[2]); +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::set_z +// Access: Published +// Description: Set light's z position +//////////////////////////////////////////////////////////////////// +INLINE void PolylightNode::set_z(float z) { + LPoint3f pos = get_pos(); + pos[2] = z; + set_pos(pos[0],pos[1],pos[2]); +} +/* +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::set_r +// Access: Published +// Description: Set light's red between 0 and 1 +//////////////////////////////////////////////////////////////////// +INLINE void PolylightNode::set_r(float r) { + _color[0]=r; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::set_g +// Access: Published +// Description: Set light's green between 0 and 1 +//////////////////////////////////////////////////////////////////// +INLINE void PolylightNode::set_g(float g) { + _color[1]=g; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::set_b +// Access: Published +// Description: Set light's blue between 0 and 1 +//////////////////////////////////////////////////////////////////// +INLINE void PolylightNode::set_b(float b) { + _color[2]=b; +} +*/ +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::get_x +// Access: Published +// Description: Get light's x position +//////////////////////////////////////////////////////////////////// +INLINE float PolylightNode::get_x() const { + return get_pos()[0]; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::get_y +// Access: Published +// Description: Get light's y position +//////////////////////////////////////////////////////////////////// +INLINE float PolylightNode::get_y() const { + return get_pos()[1]; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::get_z +// Access: Published +// Description: Get light's z position +//////////////////////////////////////////////////////////////////// +INLINE float PolylightNode::get_z() const { + return get_pos()[2]; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::get_r +// Access: Published +// Description: Get light's red color +//////////////////////////////////////////////////////////////////// +INLINE float PolylightNode::get_r() const { + return get_color()[0]; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::get_g +// Access: Published +// Description: Get light's green color +//////////////////////////////////////////////////////////////////// +INLINE float PolylightNode::get_g() const { + return get_color()[1]; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::get_b +// Access: Published +// Description: Get light's blue color +//////////////////////////////////////////////////////////////////// +INLINE float PolylightNode::get_b() const { + return get_color()[2]; +} + + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::set_freq +// Access: Published +// Description: Set frequency of sin flicker +//////////////////////////////////////////////////////////////////// +INLINE void PolylightNode::set_freq(float f) { + _sin_freq=f; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::get_freq +// Access: Published +// Description: Get frequency of sin flicker +//////////////////////////////////////////////////////////////////// +INLINE float PolylightNode::get_freq() const { + return _sin_freq; +} \ No newline at end of file diff --git a/panda/src/pgraph/polylightNode.cxx b/panda/src/pgraph/polylightNode.cxx new file mode 100755 index 0000000000..a7680a29e1 --- /dev/null +++ b/panda/src/pgraph/polylightNode.cxx @@ -0,0 +1,298 @@ +// Filename: PolylightNode.cxx +// Created by: sshodhan (02Jun04) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "PolylightNode.h" +#include "config_pgraph.h" +#include "nodePath.h" +#include "clockObject.h" +#include "bamReader.h" +#include "bamWriter.h" +#include "datagram.h" +#include "datagramIterator.h" + +#include +#include + +TypeHandle PolylightNode::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::Constructor +// Access: Published +// Description: Use PolylightNode() to construct a new +// PolylightNode object. +//////////////////////////////////////////////////////////////////// +PolylightNode:: +PolylightNode(const string &name,float x, float y, float z, + float r, float g, float b, float radius, string attenuation_type, + bool flickering, string flicker_type) : +PandaNode(name) +{ + _enabled = true; + + set_pos(x,y,z); + set_color(r,g,b); + + _radius = radius; + set_attenuation(attenuation_type); + _a0 = 1.0; + _a1 = 0.1; + _a2 = 0.01; + _flickering = flickering; + set_flicker_type(flicker_type); + _offset = -0.5; + _scale = 0.1; + _step_size = 0.1; + _sin_freq = 2.0; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::Constructor +// Access: Public +// Description: If flickering is on, the do_poly_light function +// in PolylightNodeEffect will compute this light's color +// based on the variations applied in this function +// Variation can be sin or random +// Use offset, scale and step_size to tweak +// Future addition: custom function variations to flicker +//////////////////////////////////////////////////////////////////// +Colorf PolylightNode::flicker() const { + float r,g,b; + + Colorf color; + color = get_color(); + r = color[0]; + g = color[1]; + b = color[2]; + float variation; + + if(_flicker_type == "random") { + //srand((int)ClockObject::get_global_clock()->get_frame_time()); + variation = (rand()%100);// * ClockObject::get_global_clock()->get_dt(); + variation /= 100.0; + //printf("Random Variation: %f\n",variation); + variation += _offset; + variation *= _scale; + } + else if(_flicker_type == "sin") { + double now = ClockObject::get_global_clock()->get_frame_time(); + variation = sinf(now*_sin_freq);// * ClockObject::get_global_clock()->get_dt(); + //printf("Variation: %f\n",variation); + variation += _offset; + variation *= _scale; + } + else if(_flicker_type == "fixed_point") { + // fixed point list of variation values coming soon... + //double index = (ClockObject::get_global_clock()->get_frame_time() % len(fixed_points)) * ClockObject::get_global_clock()->get_dt(); + //index *= _speed; + /*if(!(int)index > len(fixed_points) { + variation = _fixed_points[(int)index]; + variation += _offset; + variation *= _scale; + }*/ + } + //printf("Variation: %f\n",variation); + r+=variation; + g+=variation; + b+=variation; + + /* CLAMPING + if(fabs(r - color[0]) > 0.5 || fabs(g - color[1]) > 0.5 || fabs(b - color[2]) > 0.5) { + r = color[0]; + g = color[1]; + b = color[2]; + } + */ + //printf("Color R:%f G:%f B:%f\n",r,g,b); + return Colorf(r,g,b,1.0); +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::compare_to +// Access: Published +// Description: Returns a number less than zero if this PolylightNode +// sorts before the other one, greater than zero if it +// sorts after, or zero if they are equivalent. +// +// Two PolylightNodes are considered equivalent if they +// consist of exactly the same properties +// Otherwise, they are different; different +// PolylightNodes will be ranked in a consistent but +// undefined ordering; the ordering is useful only for +// placing the PolylightNodes in a sorted container like an +// STL set. +//////////////////////////////////////////////////////////////////// +int PolylightNode:: +compare_to(const PolylightNode &other) const { + + if (_enabled != other._enabled) { + return _enabled ? 1 :-1; + } + + if (_radius != other._radius) { + return _radius < other._radius ? -1 :1; + } + LVecBase3f position = get_pos(); + LVecBase3f other_position = other.get_pos(); + if (position != other_position) { + return position < other_position ? -1 :1; + } + + Colorf color = get_color(); + Colorf other_color = other.get_color(); + if (color != other_color) { + return color < other_color ? -1 :1; + } + + if (_attenuation_type != other._attenuation_type) { + return _attenuation_type < other._attenuation_type ? -1 :1; + } + + if (_a0 != other._a0) { + return _a0 < other._a0 ? -1 :1; + } + + if (_a1 != other._a1) { + return _a1 < other._a1 ? -1 :1; + } + + if (_a2 != other._a2) { + return _a2 < other._a2 ? -1 :1; + } + + if (_flickering != other._flickering) { + return _flickering ? 1 :-1; + } + + if (_flicker_type != other._flicker_type) { + return _flicker_type < other._flicker_type ? -1 :1; + } + + if (_offset != other._offset) { + return _offset < other._offset ? -1 :1; + } + + if (_scale != other._scale) { + return _scale < other._scale ? -1 :1; + } + + if (_step_size != other._step_size) { + return _step_size < other._step_size ? -1 :1; + } + + if (_sin_freq != other._sin_freq) { + return _sin_freq < other._sin_freq ? -1 :1; + } + + + return 0; +} + + + + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// PolylightNode +//////////////////////////////////////////////////////////////////// +void PolylightNode:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void PolylightNode:: +write_datagram(BamWriter *manager, Datagram &dg) { + PandaNode::write_datagram(manager, dg); + LVecBase3f position; + Colorf color; + position = get_pos(); + color = get_color(); + dg.add_float32(position[0]); + dg.add_float32(position[1]); + dg.add_float32(position[2]); + dg.add_float32(color[0]); + dg.add_float32(color[1]); + dg.add_float32(color[2]); + dg.add_float32(_radius); +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type CompassEffect is encountered +// in the Bam file. It should create the CompassEffect +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *PolylightNode:: +make_from_bam(const FactoryParams ¶ms) { + PolylightNode *light = new PolylightNode(""); + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + light->fillin(scan, manager); + + return light; +} + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::fillin +// Access: Protected +// Description: This internal function is called by make_from_bam to +// read in all of the relevant data from the BamFile for +// the new CompassEffect. +//////////////////////////////////////////////////////////////////// +void PolylightNode:: +fillin(DatagramIterator &scan, BamReader *manager) { + PandaNode::fillin(scan, manager); + LVecBase3f position; + Colorf color; + position[0] = scan.get_float32(); + position[1] = scan.get_float32(); + position[2] = scan.get_float32(); + set_pos(position[0],position[1],position[2]); + color[0] = scan.get_float32(); + color[1] = scan.get_float32(); + color[2] = scan.get_float32(); + set_color(color[0], color[1], color[2]); + _radius = scan.get_float32(); +} + + + +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::output +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void PolylightNode:: +output(ostream &out) const { + out << get_type() << ":"; + //out << "Position: " << get_x() << " " << get_y() << " " << get_z() << "\n"; + //out << "Color: " << get_r() << " " << get_g() << " " << get_b() << "\n"; + out << "Radius: " << get_radius() << "\n"; +} + diff --git a/panda/src/pgraph/polylightNode.h b/panda/src/pgraph/polylightNode.h new file mode 100755 index 0000000000..2c2c24f033 --- /dev/null +++ b/panda/src/pgraph/polylightNode.h @@ -0,0 +1,150 @@ +// Filename: PolylightNode.h +// Created by: sshodhan (02Jun04) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef POLYLIGHTNODE_H +#define POLYLIGHTNODE_H + +#include "pandabase.h" + +#include "renderEffect.h" +#include "luse.h" +#include "nodePath.h" +#include "pmap.h" +#include "notify.h" +#include "pandaNode.h" + +//////////////////////////////////////////////////////////////////// +// Class : PolylightNode +// Description : A PolylightNode +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA PolylightNode : public PandaNode{ +//private: + + +PUBLISHED: + PolylightNode(const string &name, float x = 0.0, float y = 0.0, float z = 0.0, + float r = 1.0, float g = 1.0, float b = 1.0, + float radius=50.0, string attenuation_type= "linear", + bool flickering =false, string flicker_type="random"); + INLINE void enable(); + INLINE void disable(); + INLINE void set_pos(float x,float y, float z); + INLINE LVecBase3f get_pos() const; + INLINE void set_color(float r, float g, float b); + INLINE Colorf get_color() const; + INLINE void set_radius(float r); + INLINE float get_radius() const; + INLINE bool set_attenuation(string type); + INLINE string get_attenuation() const; + INLINE void set_a0(float a0); + INLINE void set_a1(float a1); + INLINE void set_a2(float a2); + INLINE float get_a0() const; + INLINE float get_a1() const; + INLINE float get_a2() const; + INLINE void flicker_on(); + INLINE void flicker_off(); + INLINE bool is_flickering() const; + INLINE bool set_flicker_type(string type); + INLINE string get_flicker_type() const; + INLINE void set_offset(float offset); + INLINE float get_offset() const; + INLINE void set_scale(float scale); + INLINE float get_scale() const; + INLINE void set_step_size(float step) ; + INLINE float get_step_size() const; + INLINE void set_x(float x); + INLINE void set_y(float y); + INLINE void set_z(float z); + //INLINE void set_r(float r); + //INLINE void set_g(float g); + //INLINE void set_b(float b); + INLINE float get_x() const; + INLINE float get_y() const; + INLINE float get_z() const; + INLINE float get_r() const; + INLINE float get_g() const; + INLINE float get_b() const; + INLINE void set_freq(float f); + INLINE float get_freq() const; + + // Comparison methods + INLINE bool operator == (const PolylightNode &other) const; + INLINE bool operator != (const PolylightNode &other) const; + INLINE bool operator < (const PolylightNode &other) const; + int compare_to(const PolylightNode &other) const; + + INLINE bool is_enabled() const; + +public: + Colorf flicker() const; + + +private: + bool _enabled; + //LPoint3f _position; + //Colorf _color; + float _radius; + string _attenuation_type; + float _a0; + float _a1; + float _a2; + bool _flickering; + string _flicker_type; + float _offset; + float _scale; + float _step_size; + float _sin_freq; + //float _speed; + //float fixed_points + + +public: + static void register_with_read_factory(); + virtual void write_datagram(BamWriter *manager, Datagram &dg); + virtual void output(ostream &out) const; + +protected: + static TypedWritable *make_from_bam(const FactoryParams ¶ms); + void fillin(DatagramIterator &scan, BamReader *manager); + + + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + RenderEffect::init_type(); + register_type(_type_handle, "PolylightNode", + RenderEffect::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "PolylightNode.I" + +#endif + +