diff --git a/panda/src/pgraph/lightAttrib.I b/panda/src/pgraph/lightAttrib.I index 7d9641496a..ed8bb1c745 100644 --- a/panda/src/pgraph/lightAttrib.I +++ b/panda/src/pgraph/lightAttrib.I @@ -19,7 +19,7 @@ //////////////////////////////////////////////////////////////////// // Function: LightAttrib::Constructor -// Access: Private +// Access: Protected // Description: Use LightAttrib::make() to construct a new // LightAttrib object. //////////////////////////////////////////////////////////////////// @@ -30,7 +30,7 @@ LightAttrib() { //////////////////////////////////////////////////////////////////// // Function: LightAttrib::Copy Constructor -// Access: Private +// Access: Protected // Description: Use LightAttrib::make() to construct a new // LightAttrib object. The copy constructor is only // defined to facilitate methods like add_on_light(). diff --git a/panda/src/pgraph/lightAttrib.h b/panda/src/pgraph/lightAttrib.h index 1a931597c6..aebccd5d77 100644 --- a/panda/src/pgraph/lightAttrib.h +++ b/panda/src/pgraph/lightAttrib.h @@ -34,7 +34,7 @@ // from the total set of "on" lights. //////////////////////////////////////////////////////////////////// class EXPCL_PANDA LightAttrib : public RenderAttrib { -private: +protected: INLINE LightAttrib(); INLINE LightAttrib(const LightAttrib ©); diff --git a/panda/src/pgraph/nodePath.cxx b/panda/src/pgraph/nodePath.cxx index 2805eaaad6..2df42c5064 100644 --- a/panda/src/pgraph/nodePath.cxx +++ b/panda/src/pgraph/nodePath.cxx @@ -2095,6 +2095,7 @@ set_light(const NodePath &light, int priority) { if (!light.is_empty()) { Light *light_obj = light.node()->as_light(); if (light_obj != (Light *)NULL) { + // It's an actual Light object. const RenderAttrib *attrib = node()->get_attrib(LightAttrib::get_class_type()); if (attrib != (const RenderAttrib *)NULL) { @@ -2112,6 +2113,31 @@ set_light(const NodePath &light, int priority) { node()->set_attrib(la->add_on_light(light), priority); } return; + + } else if (light.node()->is_of_type(PolylightNode::get_class_type())) { + // It's a Polylight object. + if (priority != 0) { + // PolylightEffects can't have a priority, since they're just + // an effect to be applied immediately. + pgraph_cat.warning() + << "Ignoring priority on set_light(" << light << ")\n"; + } + + const RenderEffect *effect = + node()->get_effect(PolylightEffect::get_class_type()); + if (effect != (const RenderEffect *)NULL) { + const PolylightEffect *ple = DCAST(PolylightEffect, effect); + + // Modify the existing PolylightEffect to add the indicated + // light. + node()->set_effect(ple->add_light(light)); + + } else { + // Create a new PolylightEffect for this node. + CPT(PolylightEffect) ple = DCAST(PolylightEffect, PolylightEffect::make()); + node()->set_effect(ple->add_light(light)); + } + return; } } nassert_raise("Not a Light object."); @@ -2135,6 +2161,7 @@ void NodePath:: set_light_off(int priority) { nassertv_always(!is_empty()); node()->set_attrib(LightAttrib::make_all_off(), priority); + node()->clear_effect(PolylightEffect::get_class_type()); } //////////////////////////////////////////////////////////////////// @@ -2224,6 +2251,16 @@ clear_light(const NodePath &light) { } } return; + + } else if (light.node()->is_of_type(PolylightNode::get_class_type())) { + const RenderEffect *effect = + node()->get_effect(PolylightEffect::get_class_type()); + if (effect != (const RenderEffect *)NULL) { + CPT(PolylightEffect) ple = DCAST(PolylightEffect, effect); + ple = DCAST(PolylightEffect, ple->remove_light(light)); + node()->set_effect(ple); + } + return; } } nassert_raise("Not a Light object."); @@ -2250,6 +2287,16 @@ has_light(const NodePath &light) const { const LightAttrib *la = DCAST(LightAttrib, attrib); return la->has_on_light(light); } + return false; + + } else if (light.node()->is_of_type(PolylightNode::get_class_type())) { + const RenderEffect *effect = + node()->get_effect(PolylightEffect::get_class_type()); + if (effect != (const RenderEffect *)NULL) { + const PolylightEffect *ple = DCAST(PolylightEffect, effect); + return ple->has_light(light); + } + return false; } } nassert_raise("Not a Light object."); diff --git a/panda/src/pgraph/polylightEffect.I b/panda/src/pgraph/polylightEffect.I index 7e0d827493..87955458d1 100755 --- a/panda/src/pgraph/polylightEffect.I +++ b/panda/src/pgraph/polylightEffect.I @@ -19,7 +19,7 @@ //////////////////////////////////////////////////////////////////// // Function: PolylightEffect::Constructor -// Access: Private +// Access: Protected // Description: Use PolylightEffect::make() to construct a new // PolylightEffect object. //////////////////////////////////////////////////////////////////// @@ -29,7 +29,7 @@ PolylightEffect() { //////////////////////////////////////////////////////////////////// // Function: PolylightEffect::Constructor -// Access: Private +// Access: Protected // Description: Copy Constructor used by the const methods // to modify data on a copy and return a new one //////////////////////////////////////////////////////////////////// @@ -55,9 +55,9 @@ get_weight() const { //////////////////////////////////////////////////////////////////// // Function: PolylightEffect::get_contrib // Access: Published -// Description: Returns CALL or CPROXIMAL +// Description: Returns CT_all or CT_proximal //////////////////////////////////////////////////////////////////// -INLINE PolylightEffect::Contrib_Type PolylightEffect:: +INLINE PolylightEffect::ContribType PolylightEffect:: get_contrib() const { return _contribution_type; } diff --git a/panda/src/pgraph/polylightEffect.cxx b/panda/src/pgraph/polylightEffect.cxx index 747ce81e15..382936499a 100755 --- a/panda/src/pgraph/polylightEffect.cxx +++ b/panda/src/pgraph/polylightEffect.cxx @@ -36,7 +36,7 @@ TypeHandle PolylightEffect::_type_handle; CPT(RenderEffect) PolylightEffect:: make() { PolylightEffect *effect = new PolylightEffect; - effect->_contribution_type = CPROXIMAL; + effect->_contribution_type = CT_proximal; effect->_weight = 0.9; effect->_effect_center = LPoint3f(0.0,0.0,0.0); return return_new(effect); @@ -48,7 +48,7 @@ make() { // Description: Constructs a new PolylightEffect object. //////////////////////////////////////////////////////////////////// CPT(RenderEffect) PolylightEffect:: -make(float weight, Contrib_Type contrib, LPoint3f effect_center) { +make(float weight, ContribType contrib, LPoint3f effect_center) { PolylightEffect *effect = new PolylightEffect; effect->_contribution_type = contrib; effect->_weight = weight; @@ -62,7 +62,8 @@ make(float weight, Contrib_Type contrib, LPoint3f effect_center) { // Description: Constructs a new PolylightEffect object. //////////////////////////////////////////////////////////////////// CPT(RenderEffect) PolylightEffect:: -make(float weight, Contrib_Type contrib, LPoint3f effect_center, LIGHTGROUP lights) { +make(float weight, ContribType contrib, LPoint3f effect_center, + const LightGroup &lights) { PolylightEffect *effect = new PolylightEffect; effect->_contribution_type = contrib; effect->_weight = weight; @@ -82,7 +83,7 @@ make(float weight, Contrib_Type contrib, LPoint3f effect_center, LIGHTGROUP ligh //////////////////////////////////////////////////////////////////// bool PolylightEffect:: has_cull_callback() const { - return true; + return !_lightgroup.empty(); } //////////////////////////////////////////////////////////////////// @@ -129,7 +130,7 @@ do_poly_light(const CullTraverserData *data, const TransformState *node_transfor r = 1.0; g = 1.0; b = 1.0; - LIGHTGROUP::const_iterator light_iter; + 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()); @@ -179,7 +180,7 @@ do_poly_light(const CullTraverserData *data, const TransformState *node_transfor } // for all lights - if ( _contribution_type == CALL) { + if ( _contribution_type == CT_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 @@ -204,6 +205,24 @@ do_poly_light(const CullTraverserData *data, const TransformState *node_transfor return ColorScaleAttrib::make(LVecBase4f(r, g, b, 1.0)); } +//////////////////////////////////////////////////////////////////// +// Function: PolylightEffect::output +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void PolylightEffect:: +output(ostream &out) const { + out << get_type() << ":"; + + LightGroup::const_iterator li; + for (li = _lightgroup.begin(); li != _lightgroup.end(); ++li) { + NodePath light = (*li); + out << " " << light; + } + out << " weight " << _weight << " contrib " << _contribution_type + << " center " << _effect_center; +} + //////////////////////////////////////////////////////////////////// // Function: PolylightEffect::compare_to_impl @@ -265,10 +284,11 @@ add_light(const NodePath &newlight) const { CPT(RenderEffect) PolylightEffect:: remove_light(const NodePath &newlight) const { PolylightEffect *effect = new PolylightEffect(*this); - LIGHTGROUP::iterator light_iter; + LightGroup::iterator light_iter; light_iter = find(effect->_lightgroup.begin(),effect->_lightgroup.end(), newlight); - if(light_iter == effect->_lightgroup.end()) { - cerr << "Light Not Found!\n"; + if (light_iter == effect->_lightgroup.end()) { + pgraph_cat.debug() + << "Attempt to remove Polylight " << newlight << "; not found.\n"; } else { // Remove light effect->_lightgroup.erase(light_iter); @@ -303,7 +323,7 @@ set_weight(float w) const { // Here, we just pass that to the make //////////////////////////////////////////////////////////////////// CPT(RenderEffect) PolylightEffect:: -set_contrib(Contrib_Type ct) const { +set_contrib(ContribType ct) const { PolylightEffect *effect = new PolylightEffect(*this); effect->_contribution_type = ct; return return_new(effect); @@ -325,3 +345,28 @@ set_effect_center(LPoint3f ec) const{ return return_new(effect); } +//////////////////////////////////////////////////////////////////// +// Function: PolylightEffect::has_light +// Access: Published +// Description: Returns true if the indicated light is listed in the +// PolylightEffect, false otherwise. +//////////////////////////////////////////////////////////////////// +bool PolylightEffect:: +has_light(const NodePath &light) const { + LightGroup::const_iterator li; + li = find(_lightgroup.begin(), _lightgroup.end(), light); + return (li != _lightgroup.end()); +} + +ostream & +operator << (ostream &out, PolylightEffect::ContribType ct) { + switch (ct) { + case PolylightEffect::CT_proximal: + return out << "proximal"; + + case PolylightEffect::CT_all: + return out << "all"; + } + + return out << "**Invalid ContribType(" << (int)ct << ")**"; +} diff --git a/panda/src/pgraph/polylightEffect.h b/panda/src/pgraph/polylightEffect.h index 7a27e619d5..aca7557ebd 100755 --- a/panda/src/pgraph/polylightEffect.h +++ b/panda/src/pgraph/polylightEffect.h @@ -40,36 +40,33 @@ // specially for night scenes //////////////////////////////////////////////////////////////////// class EXPCL_PANDA PolylightEffect : public RenderEffect { - - PUBLISHED: - enum Contrib_Type { - CPROXIMAL, - CALL, + enum ContribType { + CT_proximal, + CT_all, }; -private: + typedef pvector< NodePath > LightGroup; + +protected: INLINE PolylightEffect(); INLINE PolylightEffect(const PolylightEffect ©); - Contrib_Type _contribution_type; - float _weight; - typedef pvector< NodePath > LIGHTGROUP; - LIGHTGROUP _lightgroup; - LPoint3f _effect_center; PUBLISHED: static CPT(RenderEffect) make(); - 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); + static CPT(RenderEffect) make(float weight, ContribType contrib, LPoint3f effect_center); + static CPT(RenderEffect) make(float weight, ContribType contrib, LPoint3f effect_center, const LightGroup &lights); CPT(RenderEffect) add_light(const NodePath &newlight) const; CPT(RenderEffect) remove_light(const NodePath &newlight) const; CPT(RenderEffect) set_weight(float w) const; - CPT(RenderEffect) set_contrib(Contrib_Type c) const; + CPT(RenderEffect) set_contrib(ContribType c) const; CPT(RenderEffect) set_effect_center(LPoint3f ec) const; INLINE float get_weight() const; - INLINE Contrib_Type get_contrib() const; + INLINE ContribType get_contrib() const; INLINE LPoint3f get_effect_center()const; + bool has_light(const NodePath &light) const; + public: virtual bool has_cull_callback() const; virtual void cull_callback(CullTraverser *trav, CullTraverserData &data, @@ -78,6 +75,14 @@ public: CPT(RenderAttrib) do_poly_light(const CullTraverserData *data, const TransformState *node_transform) const; + virtual void output(ostream &out) const; + +private: + ContribType _contribution_type; + float _weight; + LightGroup _lightgroup; + LPoint3f _effect_center; + protected: virtual int compare_to_impl(const RenderEffect *other) const; @@ -101,6 +106,8 @@ private: #include "polylightEffect.I" +ostream &operator << (ostream &out, PolylightEffect::ContribType ct); + #endif diff --git a/panda/src/pgraph/textureAttrib.I b/panda/src/pgraph/textureAttrib.I index 0197827d90..0ecbb7f5fe 100644 --- a/panda/src/pgraph/textureAttrib.I +++ b/panda/src/pgraph/textureAttrib.I @@ -19,7 +19,7 @@ //////////////////////////////////////////////////////////////////// // Function: TextureAttrib::Constructor -// Access: Private +// Access: Protected // Description: Use TextureAttrib::make() to construct a new // TextureAttrib object. //////////////////////////////////////////////////////////////////// @@ -31,7 +31,7 @@ TextureAttrib() { //////////////////////////////////////////////////////////////////// // Function: TextureAttrib::Copy Constructor -// Access: Private +// Access: Protected // Description: Use TextureAttrib::make() to construct a new // TextureAttrib object. The copy constructor is only // defined to facilitate methods like add_on_stage(). diff --git a/panda/src/pgraph/textureAttrib.cxx b/panda/src/pgraph/textureAttrib.cxx index 47f159f973..4118ad7434 100644 --- a/panda/src/pgraph/textureAttrib.cxx +++ b/panda/src/pgraph/textureAttrib.cxx @@ -780,8 +780,9 @@ fillin(DatagramIterator &scan, BamReader *manager) { // Push back a NULL pointer for each off TextureStage for now, until // we get the actual list of pointers later in complete_pointers(). - //_off_stages.reserve(num_off_stages); - for (int i = 0; i < num_off_stages; i++) { + int i; + _off_stages.reserve(num_off_stages); + for (i = 0; i < num_off_stages; i++) { manager->read_pointer(scan); _off_stages.push_back(NULL); } @@ -790,7 +791,7 @@ fillin(DatagramIterator &scan, BamReader *manager) { // just read the pointers, all allocation will happen from // complete_pointers because, it is a map template we get the // actual list of pointers later in complete_pointers(). - for (int i = 0; i < _num_on_textures; i++) { + for (i = 0; i < _num_on_textures; i++) { manager->read_pointer(scan); manager->read_pointer(scan); } diff --git a/panda/src/pgraph/textureAttrib.h b/panda/src/pgraph/textureAttrib.h index b193075ae0..f2c4cef229 100644 --- a/panda/src/pgraph/textureAttrib.h +++ b/panda/src/pgraph/textureAttrib.h @@ -36,7 +36,7 @@ // secondary texture. //////////////////////////////////////////////////////////////////// class EXPCL_PANDA TextureAttrib : public RenderAttrib { -private: +protected: INLINE TextureAttrib(); INLINE TextureAttrib(const TextureAttrib ©);