robustify light interface further

This commit is contained in:
David Rose 2004-08-02 21:34:46 +00:00
parent 1707b5a38d
commit 64aece121a
22 changed files with 239 additions and 347 deletions

View File

@ -484,11 +484,11 @@ get_coordinate_system() const {
// Function: GraphicsStateGuardian::get_light
// Access: Protected
// Description: Returns the Light object that is bound to the
// indicated id, or NULL if no Light is bound.
// indicated id, or empty NodePath if no Light is bound.
////////////////////////////////////////////////////////////////////
INLINE Light *GraphicsStateGuardian::
INLINE NodePath GraphicsStateGuardian::
get_light(int light_id) const {
nassertr(light_id >= 0 && light_id < (int)_light_info.size(), (Light *)NULL);
nassertr(light_id >= 0 && light_id < (int)_light_info.size(), NodePath::fail());
return _light_info[light_id]._light;
}

View File

@ -335,7 +335,7 @@ begin_frame() {
enable_light(i, false);
_light_info[i]._enabled = false;
}
_light_info[i]._light = (Light *)NULL;
_light_info[i]._light = NodePath();
}
// Also force the lighting state to unlit, so that issue_light()
@ -683,8 +683,9 @@ issue_light(const LightAttrib *attrib) {
int num_enabled = 0;
int num_on_lights = attrib->get_num_on_lights();
for (int li = 0; li < num_on_lights; li++) {
Light *light = attrib->get_on_light(li);
nassertv(light != (Light *)NULL);
NodePath light = attrib->get_on_light(li);
nassertv(!light.is_empty() && light.node()->as_light() != (Light *)NULL);
Light *light_obj = light.node()->as_light();
num_enabled++;
@ -693,10 +694,10 @@ issue_light(const LightAttrib *attrib) {
_lighting_enabled = true;
_lighting_enabled_this_frame = true;
if (light->get_type() == AmbientLight::get_class_type()) {
if (light_obj->get_type() == AmbientLight::get_class_type()) {
// Ambient lights don't require specific light ids; simply add
// in the ambient contribution to the current total
cur_ambient_light += light->get_color();
cur_ambient_light += light_obj->get_color();
} else {
// Check to see if this light has already been bound to an id
@ -716,7 +717,7 @@ issue_light(const LightAttrib *attrib) {
// See if there are any unbound light ids
if (cur_light_id == -1) {
for (i = 0; i < max_lights; i++) {
if (_light_info[i]._light == (Light *)NULL) {
if (_light_info[i]._light.is_empty()) {
_light_info[i]._light = light;
cur_light_id = i;
break;
@ -728,7 +729,7 @@ issue_light(const LightAttrib *attrib) {
// a currently unused but previously bound id
if (cur_light_id == -1) {
for (i = 0; i < max_lights; i++) {
if (!attrib->has_light(_light_info[i]._light)) {
if (!attrib->has_on_light(_light_info[i]._light)) {
_light_info[i]._light = light;
cur_light_id = i;
break;
@ -758,11 +759,11 @@ issue_light(const LightAttrib *attrib) {
// This is the first time this frame that this light has been
// bound to this particular id.
light->bind(this, cur_light_id);
light_obj->bind(this, light, cur_light_id);
} else if (cur_light_id == -1) {
gsg_cat.warning()
<< "Failed to bind " << *light << " to id.\n";
<< "Failed to bind " << light << " to id.\n";
}
}
}
@ -949,7 +950,7 @@ issue_clip_plane(const ClipPlaneAttrib *attrib) {
// properties.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
bind_light(PointLight *light, int light_id) {
bind_light(PointLight *light_obj, const NodePath &light, int light_id) {
}
////////////////////////////////////////////////////////////////////
@ -961,7 +962,7 @@ bind_light(PointLight *light, int light_id) {
// properties.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
bind_light(DirectionalLight *light, int light_id) {
bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) {
}
////////////////////////////////////////////////////////////////////
@ -973,7 +974,7 @@ bind_light(DirectionalLight *light, int light_id) {
// properties.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
bind_light(Spotlight *light, int light_id) {
bind_light(Spotlight *light_obj, const NodePath &light, int light_id) {
}
////////////////////////////////////////////////////////////////////

View File

@ -165,12 +165,15 @@ public:
virtual void issue_color_blend(const ColorBlendAttrib *attrib);
virtual void issue_clip_plane(const ClipPlaneAttrib *attrib);
virtual void bind_light(PointLight *light, int light_id);
virtual void bind_light(DirectionalLight *light, int light_id);
virtual void bind_light(Spotlight *light, int light_id);
virtual void bind_light(PointLight *light_obj, const NodePath &light,
int light_id);
virtual void bind_light(DirectionalLight *light_obj, const NodePath &light,
int light_id);
virtual void bind_light(Spotlight *light_obj, const NodePath &light,
int light_id);
protected:
INLINE Light *get_light(int light_id) const;
INLINE NodePath get_light(int light_id) const;
virtual bool slot_new_light(int light_id);
virtual void enable_lighting(bool enable);
virtual void set_ambient_light(const Colorf &color);
@ -301,7 +304,7 @@ private:
class LightInfo {
public:
INLINE LightInfo();
PT(Light) _light;
NodePath _light;
bool _enabled;
bool _next_enabled;
};

View File

@ -2728,18 +2728,17 @@ issue_depth_offset(const DepthOffsetAttrib *attrib) {
// properties.
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
bind_light(PointLight *light, int light_id) {
bind_light(PointLight *light_obj, const NodePath &light, int light_id) {
GLenum id = get_light_id(light_id);
static const Colorf black(0.0f, 0.0f, 0.0f, 1.0f);
GLP(Lightfv)(id, GL_AMBIENT, black.get_data());
GLP(Lightfv)(id, GL_DIFFUSE, light->get_color().get_data());
GLP(Lightfv)(id, GL_SPECULAR, light->get_specular_color().get_data());
GLP(Lightfv)(id, GL_DIFFUSE, light_obj->get_color().get_data());
GLP(Lightfv)(id, GL_SPECULAR, light_obj->get_specular_color().get_data());
// Position needs to specify x, y, z, and w
// w == 1 implies non-infinite position
NodePath light_np(light);
const LMatrix4f &light_mat = light_np.get_mat(_scene_setup->get_scene_root());
LPoint3f pos = light->get_point() * light_mat;
const LMatrix4f &light_mat = light.get_mat(_scene_setup->get_scene_root());
LPoint3f pos = light_obj->get_point() * light_mat;
LPoint4f fpos(pos[0], pos[1], pos[2], 1.0f);
GLP(Lightfv)(id, GL_POSITION, fpos.get_data());
@ -2752,7 +2751,7 @@ bind_light(PointLight *light, int light_id) {
// Cutoff == 180 means uniform point light source
GLP(Lightf)(id, GL_SPOT_CUTOFF, 180.0f);
const LVecBase3f &att = light->get_attenuation();
const LVecBase3f &att = light_obj->get_attenuation();
GLP(Lightf)(id, GL_CONSTANT_ATTENUATION, att[0]);
GLP(Lightf)(id, GL_LINEAR_ATTENUATION, att[1]);
GLP(Lightf)(id, GL_QUADRATIC_ATTENUATION, att[2]);
@ -2769,18 +2768,17 @@ bind_light(PointLight *light, int light_id) {
// properties.
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
bind_light(DirectionalLight *light, int light_id) {
bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) {
GLenum id = get_light_id( light_id );
static const Colorf black(0.0f, 0.0f, 0.0f, 1.0f);
GLP(Lightfv)(id, GL_AMBIENT, black.get_data());
GLP(Lightfv)(id, GL_DIFFUSE, light->get_color().get_data());
GLP(Lightfv)(id, GL_SPECULAR, light->get_specular_color().get_data());
GLP(Lightfv)(id, GL_DIFFUSE, light_obj->get_color().get_data());
GLP(Lightfv)(id, GL_SPECULAR, light_obj->get_specular_color().get_data());
// Position needs to specify x, y, z, and w.
// w == 0 implies light is at infinity
NodePath light_np(light);
const LMatrix4f &light_mat = light_np.get_mat(_scene_setup->get_scene_root());
LVector3f dir = light->get_direction() * light_mat;
const LMatrix4f &light_mat = light.get_mat(_scene_setup->get_scene_root());
LVector3f dir = light_obj->get_direction() * light_mat;
LPoint4f fdir(-dir[0], -dir[1], -dir[2], 0);
GLP(Lightfv)(id, GL_POSITION, fdir.get_data());
@ -2811,20 +2809,19 @@ bind_light(DirectionalLight *light, int light_id) {
// properties.
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
bind_light(Spotlight *light, int light_id) {
Lens *lens = light->get_lens();
bind_light(Spotlight *light_obj, const NodePath &light, int light_id) {
Lens *lens = light_obj->get_lens();
nassertv(lens != (Lens *)NULL);
GLenum id = get_light_id(light_id);
static const Colorf black(0.0f, 0.0f, 0.0f, 1.0f);
GLP(Lightfv)(id, GL_AMBIENT, black.get_data());
GLP(Lightfv)(id, GL_DIFFUSE, light->get_color().get_data());
GLP(Lightfv)(id, GL_SPECULAR, light->get_specular_color().get_data());
GLP(Lightfv)(id, GL_DIFFUSE, light_obj->get_color().get_data());
GLP(Lightfv)(id, GL_SPECULAR, light_obj->get_specular_color().get_data());
// Position needs to specify x, y, z, and w
// w == 1 implies non-infinite position
NodePath light_np(light);
const LMatrix4f &light_mat = light_np.get_mat(_scene_setup->get_scene_root());
const LMatrix4f &light_mat = light.get_mat(_scene_setup->get_scene_root());
LPoint3f pos = lens->get_nodal_point() * light_mat;
LVector3f dir = lens->get_view_vector() * light_mat;
@ -2832,10 +2829,10 @@ bind_light(Spotlight *light, int light_id) {
GLP(Lightfv)(id, GL_POSITION, fpos.get_data());
GLP(Lightfv)(id, GL_SPOT_DIRECTION, dir.get_data());
GLP(Lightf)(id, GL_SPOT_EXPONENT, light->get_exponent());
GLP(Lightf)(id, GL_SPOT_EXPONENT, light_obj->get_exponent());
GLP(Lightf)(id, GL_SPOT_CUTOFF, lens->get_hfov());
const LVecBase3f &att = light->get_attenuation();
const LVecBase3f &att = light_obj->get_attenuation();
GLP(Lightf)(id, GL_CONSTANT_ATTENUATION, att[0]);
GLP(Lightf)(id, GL_LINEAR_ATTENUATION, att[1]);
GLP(Lightf)(id, GL_QUADRATIC_ATTENUATION, att[2]);

View File

@ -112,9 +112,12 @@ public:
virtual void issue_cg_shader_bind(const CgShaderAttrib *attrib);
// virtual void issue_stencil(const StencilAttrib *attrib);
virtual void bind_light(PointLight *light, int light_id);
virtual void bind_light(DirectionalLight *light, int light_id);
virtual void bind_light(Spotlight *light, int light_id);
virtual void bind_light(PointLight *light_obj, const NodePath &light,
int light_id);
virtual void bind_light(DirectionalLight *light_obj, const NodePath &light,
int light_id);
virtual void bind_light(Spotlight *light_obj, const NodePath &light,
int light_id);
virtual bool wants_texcoords(void) const;

View File

@ -1200,7 +1200,6 @@ fillin(DatagramIterator& scan, BamReader* manager) {
// read the multitexture data
int num_texcoords_by_names = scan.get_uint8();
// read the TexCoordsByName pointers of num_texcoords_by_names
TexCoordsByName::const_iterator tci;
_temp_texcoord_set.reserve(num_texcoords_by_names);
for (int i=0; i<num_texcoords_by_names; ++i) {
manager->read_pointer(scan);

View File

@ -28,6 +28,7 @@
class RenderBuffer;
class GraphicsWindow;
class NodePath;
class GeomContext;
class GeomNode;
@ -197,9 +198,12 @@ public:
virtual void issue_stencil(const StencilAttrib *) { }
virtual void issue_clip_plane(const ClipPlaneAttrib *) { }
virtual void bind_light(PointLight *light, int light_id) { }
virtual void bind_light(DirectionalLight *light, int light_id) { }
virtual void bind_light(Spotlight *light, int light_id) { }
virtual void bind_light(PointLight *light_obj, const NodePath &light,
int light_id) { }
virtual void bind_light(DirectionalLight *light_obj, const NodePath &light,
int light_id) { }
virtual void bind_light(Spotlight *light_obj, const NodePath &light,
int light_id) { }
PUBLISHED:
static TypeHandle get_class_type() {

View File

@ -80,7 +80,7 @@ write(ostream &out, int indent_level) const {
// Description:
////////////////////////////////////////////////////////////////////
void AmbientLight::
bind(GraphicsStateGuardianBase *, int) {
bind(GraphicsStateGuardianBase *, const NodePath &, int) {
// AmbientLights aren't bound to light id's; this function should
// never be called.
nassertv(false);

View File

@ -42,7 +42,8 @@ public:
virtual void write(ostream &out, int indent_level) const;
public:
virtual void bind(GraphicsStateGuardianBase *gsg, int light_id);
virtual void bind(GraphicsStateGuardianBase *gsg, const NodePath &light,
int light_id);
public:
static void register_with_read_factory();

View File

@ -139,8 +139,8 @@ write(ostream &out, int indent_level) const {
// Description:
////////////////////////////////////////////////////////////////////
void DirectionalLight::
bind(GraphicsStateGuardianBase *gsg, int light_id) {
gsg->bind_light(this, light_id);
bind(GraphicsStateGuardianBase *gsg, const NodePath &light, int light_id) {
gsg->bind_light(this, light, light_id);
}
////////////////////////////////////////////////////////////////////

View File

@ -51,7 +51,8 @@ PUBLISHED:
INLINE void set_direction(const LVector3f &direction);
public:
virtual void bind(GraphicsStateGuardianBase *gsg, int light_id);
virtual void bind(GraphicsStateGuardianBase *gsg, const NodePath &light,
int light_id);
private:
// This is the data that must be cycled between pipeline stages.

View File

@ -29,6 +29,7 @@
#include "pipelineCycler.h"
#include "geomNode.h"
class NodePath;
class PandaNode;
class GraphicsStateGuardianBase;
@ -58,7 +59,8 @@ PUBLISHED:
public:
virtual void output(ostream &out) const=0;
virtual void write(ostream &out, int indent_level) const=0;
virtual void bind(GraphicsStateGuardianBase *gsg, int light_id)=0;
virtual void bind(GraphicsStateGuardianBase *gsg, const NodePath &light,
int light_id)=0;
GeomNode *get_viz();

View File

@ -60,9 +60,9 @@ get_num_on_lights() const {
// Description: Returns the nth light turned on by the attribute,
// sorted in render order.
////////////////////////////////////////////////////////////////////
INLINE Light *LightAttrib::
INLINE NodePath LightAttrib::
get_on_light(int n) const {
nassertr(n >= 0 && n < (int)_on_lights.size(), (Light *)NULL);
nassertr(n >= 0 && n < (int)_on_lights.size(), NodePath::fail());
return _on_lights[n];
}
@ -73,7 +73,7 @@ get_on_light(int n) const {
// the attrib, false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool LightAttrib::
has_on_light(Light *light) const {
has_on_light(const NodePath &light) const {
return _on_lights.find(light) != _on_lights.end();
}
@ -94,9 +94,9 @@ get_num_off_lights() const {
// Description: Returns the nth light turned off by the attribute,
// sorted in arbitrary (pointer) order.
////////////////////////////////////////////////////////////////////
INLINE Light *LightAttrib::
INLINE NodePath LightAttrib::
get_off_light(int n) const {
nassertr(n >= 0 && n < (int)_off_lights.size(), (Light *)NULL);
nassertr(n >= 0 && n < (int)_off_lights.size(), NodePath::fail());
return _off_lights[n];
}
@ -107,8 +107,9 @@ get_off_light(int n) const {
// the attrib, false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool LightAttrib::
has_off_light(Light *light) const {
return _off_all_lights || _off_lights.find(light) != _off_lights.end();
has_off_light(const NodePath &light) const {
return _off_lights.find(light) != _off_lights.end() ||
(_off_all_lights && !has_on_light(light));
}
////////////////////////////////////////////////////////////////////

View File

@ -44,17 +44,17 @@ make(LightAttrib::Operation op, Light *light) {
switch (op) {
case O_set:
attrib = make_all_off();
attrib = DCAST(LightAttrib, attrib)->add_on_light(light);
attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light->as_node()));
return attrib;
case O_add:
attrib = make();
attrib = DCAST(LightAttrib, attrib)->add_on_light(light);
attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light->as_node()));
return attrib;
case O_remove:
attrib = make();
attrib = DCAST(LightAttrib, attrib)->add_off_light(light);
attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light->as_node()));
return attrib;
}
@ -78,20 +78,20 @@ make(LightAttrib::Operation op, Light *light1, Light *light2) {
switch (op) {
case O_set:
attrib = make_all_off();
attrib = DCAST(LightAttrib, attrib)->add_on_light(light1);
attrib = DCAST(LightAttrib, attrib)->add_on_light(light2);
attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light1->as_node()));
attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light2->as_node()));
return attrib;
case O_add:
attrib = make();
attrib = DCAST(LightAttrib, attrib)->add_on_light(light1);
attrib = DCAST(LightAttrib, attrib)->add_on_light(light2);
attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light1->as_node()));
attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light2->as_node()));
return attrib;
case O_remove:
attrib = make();
attrib = DCAST(LightAttrib, attrib)->add_off_light(light1);
attrib = DCAST(LightAttrib, attrib)->add_off_light(light2);
attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light1->as_node()));
attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light2->as_node()));
return attrib;
}
@ -116,23 +116,23 @@ make(LightAttrib::Operation op, Light *light1, Light *light2,
switch (op) {
case O_set:
attrib = make_all_off();
attrib = DCAST(LightAttrib, attrib)->add_on_light(light1);
attrib = DCAST(LightAttrib, attrib)->add_on_light(light2);
attrib = DCAST(LightAttrib, attrib)->add_on_light(light3);
attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light1->as_node()));
attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light2->as_node()));
attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light3->as_node()));
return attrib;
case O_add:
attrib = make();
attrib = DCAST(LightAttrib, attrib)->add_on_light(light1);
attrib = DCAST(LightAttrib, attrib)->add_on_light(light2);
attrib = DCAST(LightAttrib, attrib)->add_on_light(light3);
attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light1->as_node()));
attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light2->as_node()));
attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light3->as_node()));
return attrib;
case O_remove:
attrib = make();
attrib = DCAST(LightAttrib, attrib)->add_off_light(light1);
attrib = DCAST(LightAttrib, attrib)->add_off_light(light2);
attrib = DCAST(LightAttrib, attrib)->add_off_light(light3);
attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light1->as_node()));
attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light2->as_node()));
attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light3->as_node()));
return attrib;
}
@ -157,26 +157,26 @@ make(LightAttrib::Operation op, Light *light1, Light *light2,
switch (op) {
case O_set:
attrib = make_all_off();
attrib = DCAST(LightAttrib, attrib)->add_on_light(light1);
attrib = DCAST(LightAttrib, attrib)->add_on_light(light2);
attrib = DCAST(LightAttrib, attrib)->add_on_light(light3);
attrib = DCAST(LightAttrib, attrib)->add_on_light(light4);
attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light1->as_node()));
attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light2->as_node()));
attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light3->as_node()));
attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light4->as_node()));
return attrib;
case O_add:
attrib = make();
attrib = DCAST(LightAttrib, attrib)->add_on_light(light1);
attrib = DCAST(LightAttrib, attrib)->add_on_light(light2);
attrib = DCAST(LightAttrib, attrib)->add_on_light(light3);
attrib = DCAST(LightAttrib, attrib)->add_on_light(light4);
attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light1->as_node()));
attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light2->as_node()));
attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light3->as_node()));
attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light4->as_node()));
return attrib;
case O_remove:
attrib = make();
attrib = DCAST(LightAttrib, attrib)->add_off_light(light1);
attrib = DCAST(LightAttrib, attrib)->add_off_light(light2);
attrib = DCAST(LightAttrib, attrib)->add_off_light(light3);
attrib = DCAST(LightAttrib, attrib)->add_off_light(light4);
attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light1->as_node()));
attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light2->as_node()));
attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light3->as_node()));
attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light4->as_node()));
return attrib;
}
@ -235,7 +235,7 @@ get_num_lights() const {
////////////////////////////////////////////////////////////////////
// Function: LightAttrib::get_light
// Access: Published
// Description: Returns the nth lights listed in the attribute.
// Description: Returns the nth light listed in the attribute.
//
// This method is now deprecated. LightAttribs nowadays
// have a separate list of on_lights and off_lights, so
@ -245,9 +245,9 @@ get_num_lights() const {
Light *LightAttrib::
get_light(int n) const {
if (get_num_off_lights() == 0) {
return get_on_light(n);
return get_on_light(n).node()->as_light();
} else {
return get_off_light(n);
return get_off_light(n).node()->as_light();
}
}
@ -265,9 +265,9 @@ get_light(int n) const {
bool LightAttrib::
has_light(Light *light) const {
if (get_num_off_lights() == 0) {
return has_on_light(light);
return has_on_light(NodePath(light->as_node()));
} else {
return has_off_light(light);
return has_off_light(NodePath(light->as_node()));
}
}
@ -283,9 +283,9 @@ has_light(Light *light) const {
CPT(RenderAttrib) LightAttrib::
add_light(Light *light) const {
if (get_num_off_lights() == 0) {
return add_on_light(light);
return add_on_light(NodePath(light->as_node()));
} else {
return add_off_light(light);
return add_off_light(NodePath(light->as_node()));
}
}
@ -302,9 +302,9 @@ add_light(Light *light) const {
CPT(RenderAttrib) LightAttrib::
remove_light(Light *light) const {
if (get_num_off_lights() == 0) {
return remove_on_light(light);
return remove_on_light(NodePath(light->as_node()));
} else {
return remove_off_light(light);
return remove_off_light(NodePath(light->as_node()));
}
}
@ -352,7 +352,8 @@ make_all_off() {
// turned on by this attrib.
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) LightAttrib::
add_on_light(Light *light) const {
add_on_light(const NodePath &light) const {
nassertr(!light.is_empty() && light.node()->as_light() != (Light *)NULL, this);
LightAttrib *attrib = new LightAttrib(*this);
attrib->_on_lights.insert(light);
attrib->_off_lights.erase(light);
@ -375,7 +376,8 @@ add_on_light(Light *light) const {
// lights turned on by this attrib.
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) LightAttrib::
remove_on_light(Light *light) const {
remove_on_light(const NodePath &light) const {
nassertr(!light.is_empty() && light.node()->as_light() != (Light *)NULL, this);
LightAttrib *attrib = new LightAttrib(*this);
attrib->_on_lights.erase(light);
return return_new(attrib);
@ -389,7 +391,8 @@ remove_on_light(Light *light) const {
// turned off by this attrib.
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) LightAttrib::
add_off_light(Light *light) const {
add_off_light(const NodePath &light) const {
nassertr(!light.is_empty() && light.node()->as_light() != (Light *)NULL, this);
LightAttrib *attrib = new LightAttrib(*this);
if (!_off_all_lights) {
attrib->_off_lights.insert(light);
@ -406,7 +409,8 @@ add_off_light(Light *light) const {
// lights turned off by this attrib.
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) LightAttrib::
remove_off_light(Light *light) const {
remove_off_light(const NodePath &light) const {
nassertr(!light.is_empty() && light.node()->as_light() != (Light *)NULL, this);
LightAttrib *attrib = new LightAttrib(*this);
attrib->_off_lights.erase(light);
return return_new(attrib);
@ -453,8 +457,8 @@ output(ostream &out) const {
out << "off";
Lights::const_iterator fi;
for (fi = _off_lights.begin(); fi != _off_lights.end(); ++fi) {
Light *light = (*fi);
out << " " << *light;
NodePath light = (*fi);
out << " " << light;
}
if (!_on_lights.empty()) {
@ -464,8 +468,8 @@ output(ostream &out) const {
Lights::const_iterator li;
for (li = _on_lights.begin(); li != _on_lights.end(); ++li) {
Light *light = (*li);
out << " " << *light;
NodePath light = (*li);
out << " " << light;
}
}
@ -497,11 +501,12 @@ compare_to_impl(const RenderAttrib *other) const {
Lights::const_iterator oli = ta->_on_lights.begin();
while (li != _on_lights.end() && oli != ta->_on_lights.end()) {
Light *light = (*li);
Light *other_light = (*oli);
NodePath light = (*li);
NodePath other_light = (*oli);
if (light != other_light) {
return light < other_light ? -1 : 1;
int compare = light.compare_to(other_light);
if (compare != 0) {
return compare;
}
++li;
@ -519,11 +524,12 @@ compare_to_impl(const RenderAttrib *other) const {
Lights::const_iterator ofi = ta->_off_lights.begin();
while (fi != _off_lights.end() && ofi != ta->_off_lights.end()) {
Light *light = (*fi);
Light *other_light = (*ofi);
NodePath light = (*fi);
NodePath other_light = (*ofi);
if (light != other_light) {
return light < other_light ? -1 : 1;
int compare = light.compare_to(other_light);
if (compare != 0) {
return compare;
}
++fi;
@ -612,7 +618,7 @@ compose_impl(const RenderAttrib *other) const {
} else { // (*bi) == (*ai)
// Here is a light we have in both.
*result = *ai;
*result = *bi;
++ai;
++bi;
++result;
@ -636,7 +642,7 @@ compose_impl(const RenderAttrib *other) const {
} else {
// Here is a light we have in both.
*result = *ai;
*result = *bi;
++ai;
++bi;
++result;
@ -740,8 +746,10 @@ write_datagram(BamWriter *manager, Datagram &dg) {
// write the off lights pointers if any
Lights::const_iterator fi;
for (fi = _off_lights.begin(); fi != _off_lights.end(); ++fi) {
Light *light = (*fi);
manager->write_pointer(dg, light->as_node());
NodePath light = (*fi);
// Whoops, we don't have a way to write out a NodePath right now.
manager->write_pointer(dg, light.node());
}
// write the number of on lights
@ -749,8 +757,8 @@ write_datagram(BamWriter *manager, Datagram &dg) {
// write the on lights pointers if any
Lights::const_iterator nti;
for (nti = _on_lights.begin(); nti != _on_lights.end(); ++nti) {
Light *light = (*nti);
manager->write_pointer(dg, light->as_node());
NodePath light = (*nti);
manager->write_pointer(dg, light.node());
}
}
@ -769,7 +777,7 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
while (ci != _off_lights.end()) {
PandaNode *node;
DCAST_INTO_R(node, p_list[pi++], pi);
(*ci) = node->as_light();
(*ci) = NodePath(node);
++ci;
}
@ -777,7 +785,7 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
while (ci != _on_lights.end()) {
PandaNode *node;
DCAST_INTO_R(node, p_list[pi++], pi);
(*ci) = node->as_light();
(*ci) = NodePath(node);
++ci;
}

View File

@ -24,6 +24,7 @@
#include "light.h"
#include "renderAttrib.h"
#include "ordered_vector.h"
#include "nodePath.h"
////////////////////////////////////////////////////////////////////
// Class : LightAttrib
@ -74,20 +75,20 @@ PUBLISHED:
static CPT(RenderAttrib) make_all_off();
INLINE int get_num_on_lights() const;
INLINE Light *get_on_light(int n) const;
INLINE bool has_on_light(Light *light) const;
INLINE NodePath get_on_light(int n) const;
INLINE bool has_on_light(const NodePath &light) const;
INLINE int get_num_off_lights() const;
INLINE Light *get_off_light(int n) const;
INLINE bool has_off_light(Light *light) const;
INLINE NodePath get_off_light(int n) const;
INLINE bool has_off_light(const NodePath &light) const;
INLINE bool has_all_off() const;
INLINE bool is_identity() const;
CPT(RenderAttrib) add_on_light(Light *light) const;
CPT(RenderAttrib) remove_on_light(Light *light) const;
CPT(RenderAttrib) add_off_light(Light *light) const;
CPT(RenderAttrib) remove_off_light(Light *light) const;
CPT(RenderAttrib) add_on_light(const NodePath &light) const;
CPT(RenderAttrib) remove_on_light(const NodePath &light) const;
CPT(RenderAttrib) add_off_light(const NodePath &light) const;
CPT(RenderAttrib) remove_off_light(const NodePath &light) const;
public:
virtual void issue(GraphicsStateGuardianBase *gsg) const;
@ -100,7 +101,7 @@ protected:
virtual RenderAttrib *make_default_impl() const;
private:
typedef ov_set< PT(Light) > Lights;
typedef ov_set<NodePath> Lights;
Lights _on_lights, _off_lights;
bool _off_all_lights;

View File

@ -2024,54 +2024,6 @@ get_color_scale() const {
return ident_scale;
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::set_light
// Access: Published
// Description: Adds the indicated Light to the list of lights that
// illuminate geometry at this node and below. The
// light itself should be parented into the scene graph
// elsewhere, to represent the light's position in
// space; but until set_light() is called it will
// illuminate no geometry.
////////////////////////////////////////////////////////////////////
void NodePath::
set_light(Light *light, int priority) {
nassertv_always(!is_empty());
const RenderAttrib *attrib =
node()->get_attrib(LightAttrib::get_class_type());
if (attrib != (const RenderAttrib *)NULL) {
priority = max(priority,
node()->get_state()->get_override(LightAttrib::get_class_type()));
const LightAttrib *la = DCAST(LightAttrib, attrib);
// Modify the existing LightAttrib to add the indicated
// light.
node()->set_attrib(la->add_on_light(light), priority);
} else {
// Create a new LightAttrib for this node.
CPT(LightAttrib) la = DCAST(LightAttrib, LightAttrib::make());
node()->set_attrib(la->add_on_light(light), priority);
}
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::set_light
// Access: Published
// Description: Adds a PolylightEffect to the geometry at this node
// and below. This makes the geometry at this point in
// the scene graph grow brighter or dimmer according to
// its proximity to the indicated PolylightNode; this is
// an effect similar to lighting, but is not related to
// traditional hardware T&L.
////////////////////////////////////////////////////////////////////
void NodePath::
set_light(PolylightNode *) {
// Not yet implemented.
nassertv(false);
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::set_light
// Access: Published
@ -2084,11 +2036,26 @@ set_light(PolylightNode *) {
////////////////////////////////////////////////////////////////////
void NodePath::
set_light(const NodePath &light, int priority) {
nassertv_always(!is_empty());
if (!light.is_empty()) {
PandaNode *node = light.node();
Light *light_obj = node->as_light();
Light *light_obj = light.node()->as_light();
if (light_obj != (Light *)NULL) {
set_light(light_obj, priority);
const RenderAttrib *attrib =
node()->get_attrib(LightAttrib::get_class_type());
if (attrib != (const RenderAttrib *)NULL) {
priority = max(priority,
node()->get_state()->get_override(LightAttrib::get_class_type()));
const LightAttrib *la = DCAST(LightAttrib, attrib);
// Modify the existing LightAttrib to add the indicated
// light.
node()->set_attrib(la->add_on_light(light), priority);
} else {
// Create a new LightAttrib for this node.
CPT(LightAttrib) la = DCAST(LightAttrib, LightAttrib::make());
node()->set_attrib(la->add_on_light(light), priority);
}
return;
}
}
@ -2115,40 +2082,6 @@ set_light_off(int priority) {
node()->set_attrib(LightAttrib::make_all_off(), priority);
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::set_light_off
// Access: Published
// Description: Sets the geometry at this level and below to render
// using without the indicated Light. This is different
// from not specifying the Light; rather, this
// specifically contradicts set_light() at a higher node
// level (or, with a priority, overrides a set_light()
// at a lower level).
////////////////////////////////////////////////////////////////////
void NodePath::
set_light_off(Light *light, int priority) {
nassertv_always(!is_empty());
const RenderAttrib *attrib =
node()->get_attrib(LightAttrib::get_class_type());
if (attrib != (const RenderAttrib *)NULL) {
priority = max(priority,
node()->get_state()->get_override(LightAttrib::get_class_type()));
const LightAttrib *la = DCAST(LightAttrib, attrib);
// Modify the existing LightAttrib to add the indicated light
// to the "off" list. This also, incidentally, removes it from
// the "on" list if it is there.
node()->set_attrib(la->add_off_light(light), priority);
} else {
// Create a new LightAttrib for this node that turns off the
// indicated light.
CPT(LightAttrib) la = DCAST(LightAttrib, LightAttrib::make());
node()->set_attrib(la->add_off_light(light), priority);
}
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::set_light_off
// Access: Published
@ -2164,11 +2097,29 @@ set_light_off(Light *light, int priority) {
////////////////////////////////////////////////////////////////////
void NodePath::
set_light_off(const NodePath &light, int priority) {
nassertv_always(!is_empty());
if (!light.is_empty()) {
PandaNode *node = light.node();
Light *light_obj = node->as_light();
Light *light_obj = light.node()->as_light();
if (light_obj != (Light *)NULL) {
set_light_off(light_obj, priority);
const RenderAttrib *attrib =
node()->get_attrib(LightAttrib::get_class_type());
if (attrib != (const RenderAttrib *)NULL) {
priority = max(priority,
node()->get_state()->get_override(LightAttrib::get_class_type()));
const LightAttrib *la = DCAST(LightAttrib, attrib);
// Modify the existing LightAttrib to add the indicated light
// to the "off" list. This also, incidentally, removes it from
// the "on" list if it is there.
node()->set_attrib(la->add_off_light(light), priority);
} else {
// Create a new LightAttrib for this node that turns off the
// indicated light.
CPT(LightAttrib) la = DCAST(LightAttrib, LightAttrib::make());
node()->set_attrib(la->add_off_light(light), priority);
}
return;
}
}
@ -2189,45 +2140,6 @@ clear_light() {
node()->clear_effect(PolylightEffect::get_class_type());
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::clear_light
// Access: Published
// Description: Removes any reference to the indicated Light
// from the NodePath.
////////////////////////////////////////////////////////////////////
void NodePath::
clear_light(Light *light) {
nassertv_always(!is_empty());
const RenderAttrib *attrib =
node()->get_attrib(LightAttrib::get_class_type());
if (attrib != (const RenderAttrib *)NULL) {
CPT(LightAttrib) la = DCAST(LightAttrib, attrib);
la = DCAST(LightAttrib, la->remove_on_light(light));
la = DCAST(LightAttrib, la->remove_off_light(light));
if (la->is_identity()) {
node()->clear_attrib(LightAttrib::get_class_type());
} else {
int priority = node()->get_state()->get_override(LightAttrib::get_class_type());
node()->set_attrib(la, priority);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::clear_light
// Access: Published
// Description: Removes the indicated PolylightEffect from the
// geometry. This undoes a previous set_light() call.
////////////////////////////////////////////////////////////////////
void NodePath::
clear_light(PolylightNode *) {
// Not yet implemented.
nassertv(false);
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::clear_light
// Access: Published
@ -2236,54 +2148,32 @@ clear_light(PolylightNode *) {
////////////////////////////////////////////////////////////////////
void NodePath::
clear_light(const NodePath &light) {
nassertv_always(!is_empty());
if (!light.is_empty()) {
PandaNode *node = light.node();
Light *light_obj = node->as_light();
Light *light_obj = light.node()->as_light();
if (light_obj != (Light *)NULL) {
clear_light(light_obj);
const RenderAttrib *attrib =
node()->get_attrib(LightAttrib::get_class_type());
if (attrib != (const RenderAttrib *)NULL) {
CPT(LightAttrib) la = DCAST(LightAttrib, attrib);
la = DCAST(LightAttrib, la->remove_on_light(light));
la = DCAST(LightAttrib, la->remove_off_light(light));
if (la->is_identity()) {
node()->clear_attrib(LightAttrib::get_class_type());
} else {
int priority = node()->get_state()->get_override(LightAttrib::get_class_type());
node()->set_attrib(la, priority);
}
}
return;
}
}
nassert_raise("Not a Light object.");
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::has_light
// Access: Published
// Description: Returns true if the indicated Light has been
// specifically enabled on this particular node. This
// means that someone called set_light() on this node
// with the indicated light.
////////////////////////////////////////////////////////////////////
bool NodePath::
has_light(Light *light) const {
nassertr_always(!is_empty(), false);
const RenderAttrib *attrib =
node()->get_attrib(LightAttrib::get_class_type());
if (attrib != (const RenderAttrib *)NULL) {
const LightAttrib *la = DCAST(LightAttrib, attrib);
return la->has_on_light(light);
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::has_light
// Access: Published
// Description: Returns true if the indicated PolylightNode has been
// specifically enabled on this particular node. This
// means that someone called set_light() on this node
// with the indicated light.
////////////////////////////////////////////////////////////////////
bool NodePath::
has_light(PolylightNode *) const {
// Not yet implemented.
nassertr(false, false);
return false;
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::has_light
// Access: Published
@ -2294,11 +2184,17 @@ has_light(PolylightNode *) const {
////////////////////////////////////////////////////////////////////
bool NodePath::
has_light(const NodePath &light) const {
nassertr_always(!is_empty(), false);
if (!light.is_empty()) {
PandaNode *node = light.node();
Light *light_obj = node->as_light();
Light *light_obj = light.node()->as_light();
if (light_obj != (Light *)NULL) {
return has_light(light_obj);
const RenderAttrib *attrib =
node()->get_attrib(LightAttrib::get_class_type());
if (attrib != (const RenderAttrib *)NULL) {
const LightAttrib *la = DCAST(LightAttrib, attrib);
return la->has_on_light(light);
}
}
}
nassert_raise("Not a Light object.");
@ -2316,6 +2212,7 @@ has_light(const NodePath &light) const {
bool NodePath::
has_light_off() const {
nassertr_always(!is_empty(), false);
const RenderAttrib *attrib =
node()->get_attrib(LightAttrib::get_class_type());
if (attrib != (const RenderAttrib *)NULL) {
@ -2326,28 +2223,6 @@ has_light_off() const {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::has_light_off
// Access: Published
// Description: Returns true if the indicated Light has been
// specifically disabled on this particular node. This
// means that someone called set_light_off() on this
// node with the indicated light.
////////////////////////////////////////////////////////////////////
bool NodePath::
has_light_off(Light *light) const {
nassertr_always(!is_empty(), false);
const RenderAttrib *attrib =
node()->get_attrib(LightAttrib::get_class_type());
if (attrib != (const RenderAttrib *)NULL) {
const LightAttrib *la = DCAST(LightAttrib, attrib);
return la->has_off_light(light);
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::has_light_off
// Access: Published
@ -2361,11 +2236,16 @@ has_light_off(Light *light) const {
////////////////////////////////////////////////////////////////////
bool NodePath::
has_light_off(const NodePath &light) const {
nassertr_always(!is_empty(), false);
if (!light.is_empty()) {
PandaNode *node = light.node();
Light *light_obj = node->as_light();
Light *light_obj = light.node()->as_light();
if (light_obj != (Light *)NULL) {
return has_light(light_obj);
const RenderAttrib *attrib =
node()->get_attrib(LightAttrib::get_class_type());
if (attrib != (const RenderAttrib *)NULL) {
const LightAttrib *la = DCAST(LightAttrib, attrib);
return la->has_off_light(light);
}
}
}
nassert_raise("Not a Light object.");

View File

@ -487,25 +487,13 @@ PUBLISHED:
INLINE float get_sb() const;
INLINE float get_sa() const;
void set_light(Light *light, int priority = 0);
void set_light(PolylightNode *light);
void set_light(const NodePath &light, int priority = 0);
void set_light_off(int priority = 0);
void set_light_off(Light *light, int priority = 0);
void set_light_off(const NodePath &light, int priority = 0);
void clear_light();
void clear_light(Light *light);
void clear_light(PolylightNode *light);
void clear_light(const NodePath &light);
bool has_light(Light *light) const;
bool has_light(PolylightNode *light) const;
bool has_light(const NodePath &light) const;
bool has_light_off() const;
bool has_light_off(Light *light) const;
bool has_light_off(const NodePath &light) const;
void set_bin(const string &bin_name, int draw_order, int priority = 0);

View File

@ -138,8 +138,8 @@ write(ostream &out, int indent_level) const {
// Description:
////////////////////////////////////////////////////////////////////
void PointLight::
bind(GraphicsStateGuardianBase *gsg, int light_id) {
gsg->bind_light(this, light_id);
bind(GraphicsStateGuardianBase *gsg, const NodePath &light, int light_id) {
gsg->bind_light(this, light, light_id);
}
////////////////////////////////////////////////////////////////////

View File

@ -51,7 +51,8 @@ PUBLISHED:
INLINE void set_point(const LPoint3f &point);
public:
virtual void bind(GraphicsStateGuardianBase *gsg, int light_id);
virtual void bind(GraphicsStateGuardianBase *gsg, const NodePath &light,
int light_id);
private:
// This is the data that must be cycled between pipeline stages.

View File

@ -146,8 +146,8 @@ write(ostream &out, int indent_level) const {
// Description:
////////////////////////////////////////////////////////////////////
void Spotlight::
bind(GraphicsStateGuardianBase *gsg, int light_id) {
gsg->bind_light(this, light_id);
bind(GraphicsStateGuardianBase *gsg, const NodePath &light, int light_id) {
gsg->bind_light(this, light, light_id);
}
////////////////////////////////////////////////////////////////////

View File

@ -62,7 +62,8 @@ PUBLISHED:
INLINE void set_attenuation(const LVecBase3f &attenuation);
public:
virtual void bind(GraphicsStateGuardianBase *gsg, int light_id);
virtual void bind(GraphicsStateGuardianBase *gsg, const NodePath &light,
int light_id);
bool make_image(Texture *texture, float radius);

View File

@ -160,7 +160,8 @@ get_off_stage(int n) const {
////////////////////////////////////////////////////////////////////
INLINE bool TextureAttrib::
has_off_stage(TextureStage *stage) const {
return _off_all_stages || _off_stages.find(stage) != _off_stages.end();
return _off_stages.find(stage) != _off_stages.end() ||
(_off_all_stages && !has_on_stage(stage));
}
////////////////////////////////////////////////////////////////////