From 512acd4adffb5c25c93a82e806dedda3f72aea24 Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 12 Jul 2005 01:08:02 +0000 Subject: [PATCH] add set_priority() to Light, PlaneNode --- panda/src/display/graphicsStateGuardian.I | 32 +++++ panda/src/display/graphicsStateGuardian.cxx | 105 ++++++----------- panda/src/display/graphicsStateGuardian.h | 8 +- panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx | 41 +------ panda/src/dxgsg8/dxGraphicsStateGuardian8.h | 5 - .../glstuff/glGraphicsStateGuardian_src.cxx | 37 ------ .../src/glstuff/glGraphicsStateGuardian_src.h | 5 - panda/src/gobj/textureStage.I | 2 +- panda/src/gobj/textureStage.h | 2 + panda/src/pgraph/ambientLight.cxx | 15 +++ panda/src/pgraph/ambientLight.h | 3 + panda/src/pgraph/clipPlaneAttrib.I | 17 +++ panda/src/pgraph/clipPlaneAttrib.cxx | 83 +++++++++++++ panda/src/pgraph/clipPlaneAttrib.h | 14 ++- panda/src/pgraph/directionalLight.cxx | 15 +++ panda/src/pgraph/directionalLight.h | 2 + panda/src/pgraph/light.I | 56 ++++++++- panda/src/pgraph/light.cxx | 4 + panda/src/pgraph/light.h | 25 ++++ panda/src/pgraph/lightAttrib.I | 17 +++ panda/src/pgraph/lightAttrib.cxx | 110 ++++++++++++++++++ panda/src/pgraph/lightAttrib.h | 14 ++- panda/src/pgraph/planeNode.I | 50 ++++++++ panda/src/pgraph/planeNode.cxx | 8 +- panda/src/pgraph/planeNode.h | 13 +++ panda/src/pgraph/pointLight.cxx | 15 +++ panda/src/pgraph/pointLight.h | 2 + panda/src/pgraph/spotlight.cxx | 15 +++ panda/src/pgraph/spotlight.h | 2 + panda/src/pgraph/textureAttrib.cxx | 4 +- 30 files changed, 558 insertions(+), 163 deletions(-) diff --git a/panda/src/display/graphicsStateGuardian.I b/panda/src/display/graphicsStateGuardian.I index 5ef0b405a7..0ab727040f 100644 --- a/panda/src/display/graphicsStateGuardian.I +++ b/panda/src/display/graphicsStateGuardian.I @@ -233,6 +233,38 @@ get_max_cube_map_dimension() const { return _max_cube_map_dimension; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::get_max_lights +// Access: Published +// Description: Returns the maximum number of simultaneous lights +// that may be rendered on geometry, or -1 if there is +// no particular limit. +// +// The value returned may not be meaningful until after +// the graphics context has been fully created (e.g. the +// window has been opened). +//////////////////////////////////////////////////////////////////// +INLINE int GraphicsStateGuardian:: +get_max_lights() const { + return _max_lights; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::get_max_clip_planes +// Access: Published +// Description: Returns the maximum number of simultaneous clip planes +// that may be applied to geometry, or -1 if there is +// no particular limit. +// +// The value returned may not be meaningful until after +// the graphics context has been fully created (e.g. the +// window has been opened). +//////////////////////////////////////////////////////////////////// +INLINE int GraphicsStateGuardian:: +get_max_clip_planes() const { + return _max_clip_planes; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::get_max_vertex_transforms // Access: Published diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 215367870e..4fa62566b0 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -120,6 +120,10 @@ GraphicsStateGuardian(const FrameBufferProperties &properties, _max_3d_texture_dimension = 0; _max_cube_map_dimension = 0; + // Assume no limits on number of lights or clip planes. + _max_lights = -1; + _max_clip_planes = -1; + // Assume no vertex blending capability. _max_vertex_transforms = 0; _max_vertex_transform_indices = 0; @@ -1163,23 +1167,25 @@ issue_texture(const TextureAttrib *attrib) { // Function: GraphicsStateGuardian::issue_clip_plane // Access: Public, Virtual // Description: This is fundametically similar to issue_light(), with -// calls to slot_new_clip_plane(), apply_clip_plane(), -// and enable_clip_planes(), as appropriate. +// calls to apply_clip_plane() and enable_clip_planes(), +// as appropriate. //////////////////////////////////////////////////////////////////// void GraphicsStateGuardian:: issue_clip_plane(const ClipPlaneAttrib *attrib) { int i; - int max_planes = (int)_clip_plane_info.size(); - for (i = 0; i < max_planes; i++) { + int cur_max_planes = (int)_clip_plane_info.size(); + for (i = 0; i < cur_max_planes; i++) { _clip_plane_info[i]._next_enabled = false; } + CPT(ClipPlaneAttrib) new_attrib = attrib->filter_to_max(_max_clip_planes); + bool any_bound = false; int num_enabled = 0; - int num_on_planes = attrib->get_num_on_planes(); + int num_on_planes = new_attrib->get_num_on_planes(); for (int li = 0; li < num_on_planes; li++) { - NodePath plane = attrib->get_on_plane(li); + NodePath plane = new_attrib->get_on_plane(li); nassertv(!plane.is_empty() && plane.node()->is_of_type(PlaneNode::get_class_type())); num_enabled++; @@ -1191,7 +1197,7 @@ issue_clip_plane(const ClipPlaneAttrib *attrib) { // Check to see if this plane has already been bound to an id int cur_plane_id = -1; - for (i = 0; i < max_planes; i++) { + for (i = 0; i < cur_max_planes; i++) { if (_clip_plane_info[i]._plane == plane) { // Plane has already been bound to an id, we only need to // enable the plane, not reapply it. @@ -1205,7 +1211,7 @@ issue_clip_plane(const ClipPlaneAttrib *attrib) { // See if there are any unbound plane ids if (cur_plane_id == -1) { - for (i = 0; i < max_planes; i++) { + for (i = 0; i < cur_max_planes; i++) { if (_clip_plane_info[i]._plane.is_empty()) { _clip_plane_info[i]._plane = plane; cur_plane_id = i; @@ -1217,8 +1223,8 @@ issue_clip_plane(const ClipPlaneAttrib *attrib) { // If there were no unbound plane ids, see if we can replace // a currently unused but previously bound id if (cur_plane_id == -1) { - for (i = 0; i < max_planes; i++) { - if (!attrib->has_on_plane(_clip_plane_info[i]._plane)) { + for (i = 0; i < cur_max_planes; i++) { + if (!new_attrib->has_on_plane(_clip_plane_info[i]._plane)) { _clip_plane_info[i]._plane = plane; cur_plane_id = i; break; @@ -1228,11 +1234,11 @@ issue_clip_plane(const ClipPlaneAttrib *attrib) { // If we *still* don't have a plane id, slot a new one. if (cur_plane_id == -1) { - if (slot_new_clip_plane(max_planes)) { - cur_plane_id = max_planes; + if (_max_clip_planes < 0 || cur_max_planes < _max_clip_planes) { + cur_plane_id = cur_max_planes; _clip_plane_info.push_back(ClipPlaneInfo()); - max_planes++; - nassertv(max_planes == (int)_clip_plane_info.size()); + cur_max_planes++; + nassertv(cur_max_planes == (int)_clip_plane_info.size()); } } @@ -1257,7 +1263,7 @@ issue_clip_plane(const ClipPlaneAttrib *attrib) { } // Disable all unused planes - for (i = 0; i < max_planes; i++) { + for (i = 0; i < cur_max_planes; i++) { if (!_clip_plane_info[i]._next_enabled) { enable_clip_plane(i, false); _clip_plane_info[i]._enabled = false; @@ -1321,8 +1327,8 @@ bind_light(Spotlight *light_obj, const NodePath &light, int light_id) { // light associated with the same id where possible, but // reusing id's when necessary. When it is no longer // possible to reuse existing id's (e.g. all id's are in -// use), slot_new_light() is called to prepare the next -// sequential light id. +// use), the next sequential id is assigned (if +// available). // // It will call apply_light() each time a light is // assigned to a particular id for the first time in a @@ -1337,8 +1343,8 @@ do_issue_light() { // light list Colorf cur_ambient_light(0.0f, 0.0f, 0.0f, 0.0f); int i; - int max_lights = (int)_light_info.size(); - for (i = 0; i < max_lights; i++) { + int cur_max_lights = (int)_light_info.size(); + for (i = 0; i < cur_max_lights; i++) { _light_info[i]._next_enabled = false; } @@ -1346,9 +1352,11 @@ do_issue_light() { int num_enabled = 0; if (_pending_light != (LightAttrib *)NULL) { - int num_on_lights = _pending_light->get_num_on_lights(); + CPT(LightAttrib) new_light = _pending_light->filter_to_max(_max_lights); + + int num_on_lights = new_light->get_num_on_lights(); for (int li = 0; li < num_on_lights; li++) { - NodePath light = _pending_light->get_on_light(li); + NodePath light = new_light->get_on_light(li); nassertv(!light.is_empty() && light.node()->as_light() != (Light *)NULL); Light *light_obj = light.node()->as_light(); @@ -1367,7 +1375,7 @@ do_issue_light() { } else { // Check to see if this light has already been bound to an id int cur_light_id = -1; - for (i = 0; i < max_lights; i++) { + for (i = 0; i < cur_max_lights; i++) { if (_light_info[i]._light == light) { // Light has already been bound to an id; reuse the same id. cur_light_id = -2; @@ -1386,7 +1394,7 @@ do_issue_light() { // See if there are any unbound light ids if (cur_light_id == -1) { - for (i = 0; i < max_lights; i++) { + for (i = 0; i < cur_max_lights; i++) { if (_light_info[i]._light.is_empty()) { _light_info[i]._light = light; cur_light_id = i; @@ -1398,8 +1406,8 @@ do_issue_light() { // If there were no unbound light ids, see if we can replace // a currently unused but previously bound id if (cur_light_id == -1) { - for (i = 0; i < max_lights; i++) { - if (!_pending_light->has_on_light(_light_info[i]._light)) { + for (i = 0; i < cur_max_lights; i++) { + if (!new_light->has_on_light(_light_info[i]._light)) { _light_info[i]._light = light; cur_light_id = i; break; @@ -1409,11 +1417,11 @@ do_issue_light() { // If we *still* don't have a light id, slot a new one. if (cur_light_id == -1) { - if (slot_new_light(max_lights)) { - cur_light_id = max_lights; + if (_max_lights < 0 || cur_max_lights < _max_lights) { + cur_light_id = cur_max_lights; _light_info.push_back(LightInfo()); - max_lights++; - nassertv(max_lights == (int)_light_info.size()); + cur_max_lights++; + nassertv(cur_max_lights == (int)_light_info.size()); } } @@ -1440,7 +1448,7 @@ do_issue_light() { } // Disable all unused lights - for (i = 0; i < max_lights; i++) { + for (i = 0; i < cur_max_lights; i++) { if (!_light_info[i]._next_enabled) { enable_light(i, false); _light_info[i]._enabled = false; @@ -1491,24 +1499,6 @@ void GraphicsStateGuardian:: do_issue_texture() { } -//////////////////////////////////////////////////////////////////// -// Function: GraphicsStateGuardian::slot_new_light -// Access: Protected, Virtual -// Description: This will be called by the base class before a -// particular light id will be used for the first time. -// It is intended to allow the derived class to reserve -// any additional resources, if required, for the new -// light; and also to indicate whether the hardware -// supports this many simultaneous lights. -// -// The return value should be true if the additional -// light is supported, or false if it is not. -//////////////////////////////////////////////////////////////////// -bool GraphicsStateGuardian:: -slot_new_light(int light_id) { - return true; -} - //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::enable_lighting // Access: Protected, Virtual @@ -1573,25 +1563,6 @@ void GraphicsStateGuardian:: end_bind_lights() { } -//////////////////////////////////////////////////////////////////// -// Function: GraphicsStateGuardian::slot_new_clip_plane -// Access: Protected, Virtual -// Description: This will be called by the base class before a -// particular clip plane id will be used for the first -// time. It is intended to allow the derived class to -// reserve any additional resources, if required, for -// the new clip plane; and also to indicate whether the -// hardware supports this many simultaneous clipping -// planes. -// -// The return value should be true if the additional -// plane is supported, or false if it is not. -//////////////////////////////////////////////////////////////////// -bool GraphicsStateGuardian:: -slot_new_clip_plane(int plane_id) { - return true; -} - //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::enable_clip_planes // Access: Protected, Virtual diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index 179c01a33e..adabb7f8ad 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -94,6 +94,9 @@ PUBLISHED: INLINE int get_max_3d_texture_dimension() const; INLINE int get_max_cube_map_dimension() const; + INLINE int get_max_lights() const; + INLINE int get_max_clip_planes() const; + INLINE int get_max_vertex_transforms() const; INLINE int get_max_vertex_transform_indices() const; @@ -225,7 +228,6 @@ protected: virtual void do_issue_texture(); 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); virtual void enable_light(int light_id, bool enable); @@ -233,7 +235,6 @@ protected: virtual void end_bind_lights(); INLINE NodePath get_clip_plane(int plane_id) const; - virtual bool slot_new_clip_plane(int plane_id); virtual void enable_clip_planes(bool enable); virtual void enable_clip_plane(int plane_id, bool enable); virtual void begin_bind_clip_planes(); @@ -361,6 +362,9 @@ protected: int _max_3d_texture_dimension; int _max_cube_map_dimension; + int _max_lights; + int _max_clip_planes; + int _max_vertex_transforms; int _max_vertex_transform_indices; diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx index 3964f86dbe..36d3b5fdf1 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx @@ -1509,8 +1509,8 @@ reset() { } _max_texture_stages = d3d_caps.MaxSimultaneousTextures; - _max_lights = d3d_caps.MaxActiveLights; - _max_clip_planes = d3d_caps.MaxUserClipPlanes; + _max_lights = (int)d3d_caps.MaxActiveLights; + _max_clip_planes = (int)d3d_caps.MaxUserClipPlanes; _max_vertex_transforms = d3d_caps.MaxVertexBlendMatrices; _max_vertex_transform_indices = d3d_caps.MaxVertexBlendMatrixIndex; @@ -2293,24 +2293,6 @@ do_issue_texture() { _current_texture = new_texture; } -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::slot_new_light -// Access: Protected, Virtual -// Description: This will be called by the base class before a -// particular light id will be used for the first time. -// It is intended to allow the derived class to reserve -// any additional resources, if required, for the new -// light; and also to indicate whether the hardware -// supports this many simultaneous lights. -// -// The return value should be true if the additional -// light is supported, or false if it is not. -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -slot_new_light(int light_id) { - return ((unsigned int)light_id < _max_lights); -} - //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian8::enable_lighting // Access: Protected, Virtual @@ -2361,25 +2343,6 @@ enable_light(int light_id, bool enable) { } } -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::slot_new_clip_plane -// Access: Protected, Virtual -// Description: This will be called by the base class before a -// particular clip plane id will be used for the first -// time. It is intended to allow the derived class to -// reserve any additional resources, if required, for -// the new clip plane; and also to indicate whether the -// hardware supports this many simultaneous clipping -// planes. -// -// The return value should be true if the additional -// plane is supported, or false if it is not. -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -slot_new_clip_plane(int plane_id) { - return ((unsigned int)plane_id < _max_clip_planes); -} - //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian8::enable_clip_plane // Access: Protected, Virtual diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h index 30bc77fff9..e0c09fe089 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h @@ -121,12 +121,10 @@ protected: virtual void do_issue_material(); virtual void do_issue_texture(); - virtual bool slot_new_light(int light_id); virtual void enable_lighting(bool enable); virtual void set_ambient_light(const Colorf &color); virtual void enable_light(int light_id, bool enable); - virtual bool slot_new_clip_plane(int plane_id); virtual void enable_clip_plane(int plane_id, bool enable); virtual void bind_clip_plane(const NodePath &plane, int plane_id); @@ -223,9 +221,6 @@ protected: D3DBLEND _blend_source_func; D3DBLEND _blend_dest_func; - unsigned int _max_lights; - unsigned int _max_clip_planes; - bool _color_material_enabled; bool _texturing_enabled; bool _dither_enabled; diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 3577fdf1c8..093642a54e 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -3795,24 +3795,6 @@ get_light_color(Light *light) const { return c.get_data(); } -//////////////////////////////////////////////////////////////////// -// Function: GLGraphicsStateGuardian::slot_new_light -// Access: Protected, Virtual -// Description: This will be called by the base class before a -// particular light id will be used for the first time. -// It is intended to allow the derived class to reserve -// any additional resources, if required, for the new -// light; and also to indicate whether the hardware -// supports this many simultaneous lights. -// -// The return value should be true if the additional -// light is supported, or false if it is not. -//////////////////////////////////////////////////////////////////// -bool CLP(GraphicsStateGuardian):: -slot_new_light(int light_id) { - return (light_id < _max_lights); -} - //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::enable_lighting // Access: Protected, Virtual @@ -3908,25 +3890,6 @@ end_bind_lights() { GLP(PopMatrix)(); } -//////////////////////////////////////////////////////////////////// -// Function: GLGraphicsStateGuardian::slot_new_clip_plane -// Access: Protected, Virtual -// Description: This will be called by the base class before a -// particular clip plane id will be used for the first -// time. It is intended to allow the derived class to -// reserve any additional resources, if required, for -// the new clip plane; and also to indicate whether the -// hardware supports this many simultaneous clipping -// planes. -// -// The return value should be true if the additional -// plane is supported, or false if it is not. -//////////////////////////////////////////////////////////////////// -bool CLP(GraphicsStateGuardian):: -slot_new_clip_plane(int plane_id) { - return (plane_id < _max_clip_planes); -} - //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::enable_clip_plane // Access: Protected, Virtual diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index e70e40d5c5..56c26e9663 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -170,14 +170,12 @@ protected: bool is_at_least_version(int major_version, int minor_version, int release_version = 0) const; virtual void *get_extension_func(const char *prefix, const char *name); - virtual bool slot_new_light(int light_id); virtual void enable_lighting(bool enable); virtual void set_ambient_light(const Colorf &color); virtual void enable_light(int light_id, bool enable); virtual void begin_bind_lights(); virtual void end_bind_lights(); - virtual bool slot_new_clip_plane(int plane_id); virtual void enable_clip_plane(int plane_id, bool enable); virtual void begin_bind_clip_planes(); virtual void bind_clip_plane(const NodePath &plane, int plane_id); @@ -284,9 +282,6 @@ protected: bool _dithering_enabled; bool _texgen_forced_normal; - int _max_lights; - int _max_clip_planes; - LMatrix4f _projection_mat; int _viewport_width; int _viewport_height; diff --git a/panda/src/gobj/textureStage.I b/panda/src/gobj/textureStage.I index d50b9e7534..c6c395fffa 100755 --- a/panda/src/gobj/textureStage.I +++ b/panda/src/gobj/textureStage.I @@ -617,7 +617,7 @@ get_default() { //////////////////////////////////////////////////////////////////// // Function: TextureStage::get_sort_seq -// Access: Published, Static +// Access: Public, Static // Description: Returns a global sequence number that is incremented // any time any TextureStage in the world changes sort // or priority. This is used by TextureAttrib to diff --git a/panda/src/gobj/textureStage.h b/panda/src/gobj/textureStage.h index ceb15f4e84..063458b2a2 100644 --- a/panda/src/gobj/textureStage.h +++ b/panda/src/gobj/textureStage.h @@ -158,6 +158,8 @@ PUBLISHED: void output(ostream &out) const; INLINE static TextureStage *get_default(); + +public: INLINE static UpdateSeq get_sort_seq(); private: diff --git a/panda/src/pgraph/ambientLight.cxx b/panda/src/pgraph/ambientLight.cxx index e5f5c89744..778a03f190 100644 --- a/panda/src/pgraph/ambientLight.cxx +++ b/panda/src/pgraph/ambientLight.cxx @@ -48,6 +48,21 @@ AmbientLight(const AmbientLight ©) : { } +//////////////////////////////////////////////////////////////////// +// Function: AmbientLight::get_class_priority +// Access: Published, Virtual +// Description: Returns the relative priority associated with all +// lights of this class. This priority is used to order +// lights whose instance priority (get_priority()) is +// the same--the idea is that other things being equal, +// AmbientLights (for instance) are less important than +// DirectionalLights. +//////////////////////////////////////////////////////////////////// +int AmbientLight:: +get_class_priority() const { + return (int)CP_ambient_priority; +} + //////////////////////////////////////////////////////////////////// // Function: AmbientLight::make_copy // Access: Public, Virtual diff --git a/panda/src/pgraph/ambientLight.h b/panda/src/pgraph/ambientLight.h index 4f8248fa54..a591becaa6 100644 --- a/panda/src/pgraph/ambientLight.h +++ b/panda/src/pgraph/ambientLight.h @@ -40,6 +40,9 @@ protected: public: virtual PandaNode *make_copy() const; virtual void write(ostream &out, int indent_level) const; + +PUBLISHED: + virtual int get_class_priority() const; public: virtual void bind(GraphicsStateGuardianBase *gsg, const NodePath &light, diff --git a/panda/src/pgraph/clipPlaneAttrib.I b/panda/src/pgraph/clipPlaneAttrib.I index 01ab802c1b..232f997c4d 100644 --- a/panda/src/pgraph/clipPlaneAttrib.I +++ b/panda/src/pgraph/clipPlaneAttrib.I @@ -133,3 +133,20 @@ INLINE bool ClipPlaneAttrib:: is_identity() const { return _on_planes.empty() && _off_planes.empty() && !_off_all_planes; } + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::check_filtered +// Access: Private +// Description: Confirms whether the _filtered table is still valid. +// It may become invalid if someone calls +// PlaneNode::set_priority(). +// +// If the table is invalid, transparently empties it +// before returning. +//////////////////////////////////////////////////////////////////// +INLINE void ClipPlaneAttrib:: +check_filtered() const { + if (_sort_seq != PlaneNode::get_sort_seq()) { + ((ClipPlaneAttrib *)this)->sort_on_planes(); + } +} diff --git a/panda/src/pgraph/clipPlaneAttrib.cxx b/panda/src/pgraph/clipPlaneAttrib.cxx index 8d9916989a..01de89b5ec 100644 --- a/panda/src/pgraph/clipPlaneAttrib.cxx +++ b/panda/src/pgraph/clipPlaneAttrib.cxx @@ -29,6 +29,20 @@ CPT(RenderAttrib) ClipPlaneAttrib::_empty_attrib; CPT(RenderAttrib) ClipPlaneAttrib::_all_off_attrib; TypeHandle ClipPlaneAttrib::_type_handle; +// This STL Function object is used in filter_to_max(), below, to sort +// a list of PlaneNodes in reverse order by priority. +class ComparePlaneNodePriorities { +public: + bool operator ()(const NodePath &a, const NodePath &b) const { + nassertr(!a.is_empty() && !b.is_empty(), a < b); + PlaneNode *pa = DCAST(PlaneNode, a.node()); + PlaneNode *pb = DCAST(PlaneNode, b.node()); + nassertr(pa != (PlaneNode *)NULL && pb != (PlaneNode *)NULL, a < b); + + return pa->get_priority() > pb->get_priority(); + } +}; + //////////////////////////////////////////////////////////////////// // Function: ClipPlaneAttrib::make // Access: Published, Static @@ -447,6 +461,61 @@ remove_off_plane(const NodePath &plane) const { return return_new(attrib); } +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::filter_to_max +// Access: Public +// Description: Returns a new ClipPlaneAttrib, very much like this one, +// but with the number of on_planes reduced to be no +// more than max_clip_planes. The number of off_planes in +// the new ClipPlaneAttrib is undefined. +//////////////////////////////////////////////////////////////////// +CPT(ClipPlaneAttrib) ClipPlaneAttrib:: +filter_to_max(int max_clip_planes) const { + if (max_clip_planes < 0 || (int)_on_planes.size() <= max_clip_planes) { + // Trivial case: this ClipPlaneAttrib qualifies. + return this; + } + + // Since check_filtered() will clear the _filtered list if we are out + // of date, we should call it first. + check_filtered(); + + Filtered::const_iterator fi; + fi = _filtered.find(max_clip_planes); + if (fi != _filtered.end()) { + // Easy case: we have already computed this for this particular + // ClipPlaneAttrib. + return (*fi).second; + } + + // Harder case: we have to compute it now. We must choose the n + // planeNodes with the highest priority in our list of planeNodes. + Planes priority_planes = _on_planes; + + // This sort function uses the STL function object defined above. + sort(priority_planes.begin(), priority_planes.end(), + ComparePlaneNodePriorities()); + + // Now lop off all of the planeNodes after the first max_clip_planes. + priority_planes.erase(priority_planes.begin() + max_clip_planes, + priority_planes.end()); + + // And re-sort the ov_set into its proper order. + priority_planes.sort(); + + // Now create a new attrib reflecting these planeNodes. + PT(ClipPlaneAttrib) attrib = new ClipPlaneAttrib; + attrib->_on_planes.swap(priority_planes); + + CPT(RenderAttrib) new_attrib = return_new(attrib); + + // Finally, record this newly-created attrib in the map for next + // time. + CPT(ClipPlaneAttrib) planeNode_attrib = (const ClipPlaneAttrib *)new_attrib.p(); + ((ClipPlaneAttrib *)this)->_filtered[max_clip_planes] = planeNode_attrib; + return planeNode_attrib; +} + //////////////////////////////////////////////////////////////////// // Function: ClipPlaneAttrib::issue // Access: Public, Virtual @@ -749,6 +818,20 @@ make_default_impl() const { return new ClipPlaneAttrib; } +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::sort_on_planes +// Access: Private +// Description: This is patterned after +// TextureAttrib::sort_on_stages(), but since planeNodes +// don't actually require sorting, this only empties the +// _filtered map. +//////////////////////////////////////////////////////////////////// +void ClipPlaneAttrib:: +sort_on_planes() { + _sort_seq = PlaneNode::get_sort_seq(); + _filtered.clear(); +} + //////////////////////////////////////////////////////////////////// // Function: ClipPlaneAttrib::register_with_read_factory // Access: Public, Static diff --git a/panda/src/pgraph/clipPlaneAttrib.h b/panda/src/pgraph/clipPlaneAttrib.h index 5d46c50281..95d92b124c 100644 --- a/panda/src/pgraph/clipPlaneAttrib.h +++ b/panda/src/pgraph/clipPlaneAttrib.h @@ -23,8 +23,9 @@ #include "planeNode.h" #include "renderAttrib.h" -#include "ordered_vector.h" #include "nodePath.h" +#include "ordered_vector.h" +#include "pmap.h" //////////////////////////////////////////////////////////////////// // Class : ClipPlaneAttrib @@ -92,6 +93,8 @@ PUBLISHED: CPT(RenderAttrib) add_off_plane(const NodePath &plane) const; CPT(RenderAttrib) remove_off_plane(const NodePath &plane) const; + CPT(ClipPlaneAttrib) filter_to_max(int max_clip_planes) const; + public: virtual void issue(GraphicsStateGuardianBase *gsg) const; virtual void output(ostream &out) const; @@ -102,10 +105,19 @@ protected: virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const; virtual RenderAttrib *make_default_impl() const; +private: + INLINE void check_filtered() const; + void sort_on_planes(); + private: typedef ov_set Planes; Planes _on_planes, _off_planes; bool _off_all_planes; + + typedef pmap< int, CPT(ClipPlaneAttrib) > Filtered; + Filtered _filtered; + + UpdateSeq _sort_seq; static CPT(RenderAttrib) _empty_attrib; static CPT(RenderAttrib) _all_off_attrib; diff --git a/panda/src/pgraph/directionalLight.cxx b/panda/src/pgraph/directionalLight.cxx index a7bc477124..3cf9a7f6a3 100644 --- a/panda/src/pgraph/directionalLight.cxx +++ b/panda/src/pgraph/directionalLight.cxx @@ -159,6 +159,21 @@ get_vector_to_light(LVector3f &result, const LPoint3f &, return true; } +//////////////////////////////////////////////////////////////////// +// Function: DirectionalLight::get_class_priority +// Access: Published, Virtual +// Description: Returns the relative priority associated with all +// lights of this class. This priority is used to order +// lights whose instance priority (get_priority()) is +// the same--the idea is that other things being equal, +// AmbientLights (for instance) are less important than +// DirectionalLights. +//////////////////////////////////////////////////////////////////// +int DirectionalLight:: +get_class_priority() const { + return (int)CP_directional_priority; +} + //////////////////////////////////////////////////////////////////// // Function: DirectionalLight::bind // Access: Public, Virtual diff --git a/panda/src/pgraph/directionalLight.h b/panda/src/pgraph/directionalLight.h index 28615aebbd..ad5ac27763 100644 --- a/panda/src/pgraph/directionalLight.h +++ b/panda/src/pgraph/directionalLight.h @@ -53,6 +53,8 @@ PUBLISHED: INLINE const LVector3f &get_direction() const; INLINE void set_direction(const LVector3f &direction); + + virtual int get_class_priority() const; public: virtual void bind(GraphicsStateGuardianBase *gsg, const NodePath &light, diff --git a/panda/src/pgraph/light.I b/panda/src/pgraph/light.I index 080a5f7c2f..b005c55485 100644 --- a/panda/src/pgraph/light.I +++ b/panda/src/pgraph/light.I @@ -48,7 +48,9 @@ CData(const Light::CData ©) : // Description: //////////////////////////////////////////////////////////////////// INLINE Light:: -Light() { +Light() : + _priority(0) +{ } //////////////////////////////////////////////////////////////////// @@ -58,6 +60,7 @@ Light() { //////////////////////////////////////////////////////////////////// INLINE Light:: Light(const Light ©) : + _priority(copy._priority), _cycler(copy._cycler) { } @@ -85,9 +88,58 @@ set_color(const Colorf &color) { mark_viz_stale(); } +//////////////////////////////////////////////////////////////////// +// Function: Light::set_priority +// Access: Published +// Description: Changes the relative importance of this light +// relative to the other lights that are applied +// simultaneously. +// +// The priority number is used to decide which of the +// requested lights are to be selected for rendering +// when more lights are requested than the hardware will +// support. The highest-priority n lights are selected +// for rendering. +// +// This is similar to TextureStage::set_priority(). +//////////////////////////////////////////////////////////////////// +INLINE void Light:: +set_priority(int priority) { + _priority = priority; + + // Update the global flag to indicate that all LightAttribs in the + // world must now re-sort their lists. + _sort_seq++; +} + +//////////////////////////////////////////////////////////////////// +// Function: Light::get_priority +// Access: Published +// Description: Returns the priority associated with this light. See +// set_priority(). +//////////////////////////////////////////////////////////////////// +INLINE int Light:: +get_priority() const { + return _priority; +} + +//////////////////////////////////////////////////////////////////// +// Function: Light::get_sort_seq +// Access: Public, Static +// Description: Returns a global sequence number that is incremented +// any time any Light in the world changes sort +// or priority. This is used by LightAttrib to +// determine when it is necessary to re-sort its +// internal array of stages. +//////////////////////////////////////////////////////////////////// +INLINE UpdateSeq Light:: +get_sort_seq() { + return _sort_seq; +} + //////////////////////////////////////////////////////////////////// // Function: Light::mark_viz_stale -// Access: Public +// Access: Protected // Description: Indicates that the internal visualization object will // need to be updated. //////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgraph/light.cxx b/panda/src/pgraph/light.cxx index b5697a9b90..a1e8d7126a 100644 --- a/panda/src/pgraph/light.cxx +++ b/panda/src/pgraph/light.cxx @@ -22,6 +22,8 @@ #include "datagram.h" #include "datagramIterator.h" +UpdateSeq Light::_sort_seq; + TypeHandle Light::_type_handle; @@ -128,6 +130,7 @@ fill_viz_geom(GeomNode *) { void Light:: write_datagram(BamWriter *manager, Datagram &dg) { manager->write_cdata(dg, _cycler); + dg.add_int32(_priority); } //////////////////////////////////////////////////////////////////// @@ -140,4 +143,5 @@ write_datagram(BamWriter *manager, Datagram &dg) { void Light:: fillin(DatagramIterator &scan, BamReader *manager) { manager->read_cdata(scan, _cycler); + _priority = scan.get_int32(); } diff --git a/panda/src/pgraph/light.h b/panda/src/pgraph/light.h index 930bf72983..294deb3984 100644 --- a/panda/src/pgraph/light.h +++ b/panda/src/pgraph/light.h @@ -27,6 +27,7 @@ #include "cycleDataReader.h" #include "cycleDataWriter.h" #include "pipelineCycler.h" +#include "updateSeq.h" #include "geomNode.h" class NodePath; @@ -56,6 +57,10 @@ PUBLISHED: INLINE const Colorf &get_color() const; INLINE void set_color(const Colorf &color); + INLINE void set_priority(int priority); + INLINE int get_priority() const; + virtual int get_class_priority() const=0; + public: virtual void output(ostream &out) const=0; virtual void write(ostream &out, int indent_level) const=0; @@ -68,11 +73,31 @@ public: GeomNode *get_viz(); + INLINE static UpdateSeq get_sort_seq(); + protected: virtual void fill_viz_geom(GeomNode *viz_geom); INLINE void mark_viz_stale(); + + // This enumerated class defines the relative class priority of + // different kinds of lights. This hierarchy is only used to + // resolve multiple lights of the same priority specified by + // set_priority(). In general, the first items in this list have a + // lesser priority than later items. + enum ClassPriority { + CP_ambient_priority, + CP_point_priority, + CP_directional_priority, + CP_spot_priority, + }; private: + // The priority is not cycled, because there's no real reason to do + // so, and cycling it makes it difficult to synchronize with the + // LightAttribs. + int _priority; + static UpdateSeq _sort_seq; + // This is the data that must be cycled between pipeline stages. class EXPCL_PANDA CData : public CycleData { public: diff --git a/panda/src/pgraph/lightAttrib.I b/panda/src/pgraph/lightAttrib.I index ed8bb1c745..8d5f0db623 100644 --- a/panda/src/pgraph/lightAttrib.I +++ b/panda/src/pgraph/lightAttrib.I @@ -133,3 +133,20 @@ INLINE bool LightAttrib:: is_identity() const { return _on_lights.empty() && _off_lights.empty() && !_off_all_lights; } + +//////////////////////////////////////////////////////////////////// +// Function: LightAttrib::check_filtered +// Access: Private +// Description: Confirms whether the _filtered table is still valid. +// It may become invalid if someone calls +// Light::set_priority(). +// +// If the table is invalid, transparently empties it +// before returning. +//////////////////////////////////////////////////////////////////// +INLINE void LightAttrib:: +check_filtered() const { + if (_sort_seq != Light::get_sort_seq()) { + ((LightAttrib *)this)->sort_on_lights(); + } +} diff --git a/panda/src/pgraph/lightAttrib.cxx b/panda/src/pgraph/lightAttrib.cxx index 98818c4797..080dd02219 100644 --- a/panda/src/pgraph/lightAttrib.cxx +++ b/panda/src/pgraph/lightAttrib.cxx @@ -17,6 +17,7 @@ //////////////////////////////////////////////////////////////////// #include "lightAttrib.h" +#include "ambientLight.h" #include "pandaNode.h" #include "nodePath.h" #include "graphicsStateGuardianBase.h" @@ -30,6 +31,24 @@ CPT(RenderAttrib) LightAttrib::_empty_attrib; CPT(RenderAttrib) LightAttrib::_all_off_attrib; TypeHandle LightAttrib::_type_handle; +// This STL Function object is used in filter_to_max(), below, to sort +// a list of Lights in reverse order by priority. In the case of two +// lights with equal priority, the class priority is compared. +class CompareLightPriorities { +public: + bool operator ()(const NodePath &a, const NodePath &b) const { + nassertr(!a.is_empty() && !b.is_empty(), a < b); + Light *la = a.node()->as_light(); + Light *lb = b.node()->as_light(); + nassertr(la != (Light *)NULL && lb != (Light *)NULL, a < b); + + if (la->get_priority() != lb->get_priority()) { + return la->get_priority() > lb->get_priority(); + } + return la->get_class_priority() > lb->get_class_priority(); + } +}; + //////////////////////////////////////////////////////////////////// // Function: LightAttrib::make // Access: Published, Static @@ -448,6 +467,83 @@ remove_off_light(const NodePath &light) const { return return_new(attrib); } +//////////////////////////////////////////////////////////////////// +// Function: LightAttrib::filter_to_max +// Access: Public +// Description: Returns a new LightAttrib, very much like this one, +// but with the number of on_lights reduced to be no +// more than max_lights. The number of off_lights in +// the new LightAttrib is undefined. +// +// The number of AmbientLights is not included in the +// count. All AmbientLights in the original attrib are +// always included in the result, regardless of the +// value of max_lights. +//////////////////////////////////////////////////////////////////// +CPT(LightAttrib) LightAttrib:: +filter_to_max(int max_lights) const { + if (max_lights < 0 || (int)_on_lights.size() <= max_lights) { + // Trivial case: this LightAttrib qualifies. + return this; + } + + // Since check_filtered() will clear the _filtered list if we are out + // of date, we should call it first. + check_filtered(); + + Filtered::const_iterator fi; + fi = _filtered.find(max_lights); + if (fi != _filtered.end()) { + // Easy case: we have already computed this for this particular + // LightAttrib. + return (*fi).second; + } + + // Harder case: we have to compute it now. We must choose the n + // lights with the highest priority in our list of lights. + Lights priority_lights, ambient_lights; + + // Separate the list of lights into ambient lights and other lights. + Lights::const_iterator li; + for (li = _on_lights.begin(); li != _on_lights.end(); ++li) { + const NodePath &np = (*li); + nassertr(!np.is_empty() && np.node()->as_light() != (Light *)NULL, this); + if (np.node()->is_exact_type(AmbientLight::get_class_type())) { + ambient_lights.push_back(np); + } else { + priority_lights.push_back(np); + } + } + + // This sort function uses the STL function object defined above. + sort(priority_lights.begin(), priority_lights.end(), + CompareLightPriorities()); + + // Now lop off all of the lights after the first max_lights. + priority_lights.erase(priority_lights.begin() + max_lights, + priority_lights.end()); + + // Put the ambient lights back into the list. + for (li = ambient_lights.begin(); li != ambient_lights.end(); ++li) { + priority_lights.push_back(*li); + } + + // And re-sort the ov_set into its proper order. + priority_lights.sort(); + + // Now create a new attrib reflecting these lights. + PT(LightAttrib) attrib = new LightAttrib; + attrib->_on_lights.swap(priority_lights); + + CPT(RenderAttrib) new_attrib = return_new(attrib); + + // Finally, record this newly-created attrib in the map for next + // time. + CPT(LightAttrib) light_attrib = (const LightAttrib *)new_attrib.p(); + ((LightAttrib *)this)->_filtered[max_lights] = light_attrib; + return light_attrib; +} + //////////////////////////////////////////////////////////////////// // Function: LightAttrib::issue // Access: Public, Virtual @@ -750,6 +846,20 @@ make_default_impl() const { return new LightAttrib; } +//////////////////////////////////////////////////////////////////// +// Function: LightAttrib::sort_on_lights +// Access: Private +// Description: This is patterned after +// TextureAttrib::sort_on_stages(), but since lights +// don't actually require sorting, this only empties the +// _filtered map. +//////////////////////////////////////////////////////////////////// +void LightAttrib:: +sort_on_lights() { + _sort_seq = Light::get_sort_seq(); + _filtered.clear(); +} + //////////////////////////////////////////////////////////////////// // Function: LightAttrib::register_with_read_factory // Access: Public, Static diff --git a/panda/src/pgraph/lightAttrib.h b/panda/src/pgraph/lightAttrib.h index aebccd5d77..ceaf293644 100644 --- a/panda/src/pgraph/lightAttrib.h +++ b/panda/src/pgraph/lightAttrib.h @@ -23,8 +23,9 @@ #include "light.h" #include "renderAttrib.h" -#include "ordered_vector.h" #include "nodePath.h" +#include "ordered_vector.h" +#include "pmap.h" //////////////////////////////////////////////////////////////////// // Class : LightAttrib @@ -90,6 +91,8 @@ PUBLISHED: CPT(RenderAttrib) add_off_light(const NodePath &light) const; CPT(RenderAttrib) remove_off_light(const NodePath &light) const; + CPT(LightAttrib) filter_to_max(int max_lights) const; + public: virtual void issue(GraphicsStateGuardianBase *gsg) const; virtual void output(ostream &out) const; @@ -100,11 +103,20 @@ protected: virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const; virtual RenderAttrib *make_default_impl() const; +private: + INLINE void check_filtered() const; + void sort_on_lights(); + private: typedef ov_set Lights; Lights _on_lights, _off_lights; bool _off_all_lights; + typedef pmap< int, CPT(LightAttrib) > Filtered; + Filtered _filtered; + + UpdateSeq _sort_seq; + static CPT(RenderAttrib) _empty_attrib; static CPT(RenderAttrib) _all_off_attrib; diff --git a/panda/src/pgraph/planeNode.I b/panda/src/pgraph/planeNode.I index 6d2e41a7d7..97b33af95f 100644 --- a/panda/src/pgraph/planeNode.I +++ b/panda/src/pgraph/planeNode.I @@ -61,3 +61,53 @@ get_plane() const { CDReader cdata(_cycler); return cdata->_plane; } + +//////////////////////////////////////////////////////////////////// +// Function: PlaneNode::set_priority +// Access: Published +// Description: Changes the relative importance of this PlaneNode +// (when it is used as a clip plane) relative to the +// other clip planes that are applied simultaneously. +// +// The priority number is used to decide which of the +// requested clip planes are to be activated when more +// clip planes are requested than the hardware will +// support. The highest-priority n planes are selected +// for rendering. +// +// This is similar to TextureStage::set_priority(). +//////////////////////////////////////////////////////////////////// +INLINE void PlaneNode:: +set_priority(int priority) { + _priority = priority; + + // Update the global flag to indicate that all ClipPlaneAttribs in + // the world must now re-sort their lists. + _sort_seq++; +} + +//////////////////////////////////////////////////////////////////// +// Function: PlaneNode::get_priority +// Access: Published +// Description: Returns the priority associated with this clip +// plane. See set_priority(). +//////////////////////////////////////////////////////////////////// +INLINE int PlaneNode:: +get_priority() const { + return _priority; +} + +//////////////////////////////////////////////////////////////////// +// Function: PlaneNode::get_sort_seq +// Access: Public, Static +// Description: Returns a global sequence number that is incremented +// any time any PlaneNode in the world changes sort +// or priority. This is used by ClipPlaneAttrib to +// determine when it is necessary to re-sort its +// internal array of stages. +//////////////////////////////////////////////////////////////////// +INLINE UpdateSeq PlaneNode:: +get_sort_seq() { + return _sort_seq; +} + diff --git a/panda/src/pgraph/planeNode.cxx b/panda/src/pgraph/planeNode.cxx index 394596fbb3..b3a623e325 100644 --- a/panda/src/pgraph/planeNode.cxx +++ b/panda/src/pgraph/planeNode.cxx @@ -23,6 +23,8 @@ #include "datagram.h" #include "datagramIterator.h" +UpdateSeq PlaneNode::_sort_seq; + TypeHandle PlaneNode::_type_handle; //////////////////////////////////////////////////////////////////// @@ -65,7 +67,8 @@ fillin(DatagramIterator &scan, BamReader *) { //////////////////////////////////////////////////////////////////// PlaneNode:: PlaneNode(const string &name) : - PandaNode(name) + PandaNode(name), + _priority(0) { } @@ -77,6 +80,7 @@ PlaneNode(const string &name) : PlaneNode:: PlaneNode(const PlaneNode ©) : PandaNode(copy), + _priority(copy._priority), _cycler(copy._cycler) { } @@ -151,6 +155,7 @@ void PlaneNode:: write_datagram(BamWriter *manager, Datagram &dg) { PandaNode::write_datagram(manager, dg); manager->write_cdata(dg, _cycler); + dg.add_int32(_priority); } //////////////////////////////////////////////////////////////////// @@ -184,4 +189,5 @@ void PlaneNode:: fillin(DatagramIterator &scan, BamReader *manager) { PandaNode::fillin(scan, manager); manager->read_cdata(scan, _cycler); + _priority = scan.get_int32(); } diff --git a/panda/src/pgraph/planeNode.h b/panda/src/pgraph/planeNode.h index 40aa709df2..37b1ebfe4a 100644 --- a/panda/src/pgraph/planeNode.h +++ b/panda/src/pgraph/planeNode.h @@ -23,6 +23,7 @@ #include "plane.h" #include "pandaNode.h" +#include "updateSeq.h" //////////////////////////////////////////////////////////////////// // Class : PlaneNode @@ -48,7 +49,19 @@ PUBLISHED: INLINE void set_plane(const Planef &plane); INLINE const Planef &get_plane() const; + INLINE void set_priority(int priority); + INLINE int get_priority() const; + +public: + INLINE static UpdateSeq get_sort_seq(); + private: + // The priority is not cycled, because there's no real reason to do + // so, and cycling it makes it difficult to synchronize with the + // ClipPlaneAttribs. + int _priority; + static UpdateSeq _sort_seq; + // This is the data that must be cycled between pipeline stages. class EXPCL_PANDA CData : public CycleData { public: diff --git a/panda/src/pgraph/pointLight.cxx b/panda/src/pgraph/pointLight.cxx index 6e5027a1a4..770d295fdb 100644 --- a/panda/src/pgraph/pointLight.cxx +++ b/panda/src/pgraph/pointLight.cxx @@ -159,6 +159,21 @@ get_vector_to_light(LVector3f &result, const LPoint3f &from_object_point, return true; } +//////////////////////////////////////////////////////////////////// +// Function: PointLight::get_class_priority +// Access: Published, Virtual +// Description: Returns the relative priority associated with all +// lights of this class. This priority is used to order +// lights whose instance priority (get_priority()) is +// the same--the idea is that other things being equal, +// AmbientLights (for instance) are less important than +// DirectionalLights. +//////////////////////////////////////////////////////////////////// +int PointLight:: +get_class_priority() const { + return (int)CP_point_priority; +} + //////////////////////////////////////////////////////////////////// // Function: PointLight::bind // Access: Public, Virtual diff --git a/panda/src/pgraph/pointLight.h b/panda/src/pgraph/pointLight.h index 3b3599dc86..1fa21fa952 100644 --- a/panda/src/pgraph/pointLight.h +++ b/panda/src/pgraph/pointLight.h @@ -53,6 +53,8 @@ PUBLISHED: INLINE const LPoint3f &get_point() const; INLINE void set_point(const LPoint3f &point); + + virtual int get_class_priority() const; public: virtual void bind(GraphicsStateGuardianBase *gsg, const NodePath &light, diff --git a/panda/src/pgraph/spotlight.cxx b/panda/src/pgraph/spotlight.cxx index 7d6246c652..1ca77aee63 100644 --- a/panda/src/pgraph/spotlight.cxx +++ b/panda/src/pgraph/spotlight.cxx @@ -212,6 +212,21 @@ make_spot(int pixel_width, float full_radius, Colorf &fg, Colorf &bg) { return tex; } +//////////////////////////////////////////////////////////////////// +// Function: Spotlight::get_class_priority +// Access: Published, Virtual +// Description: Returns the relative priority associated with all +// lights of this class. This priority is used to order +// lights whose instance priority (get_priority()) is +// the same--the idea is that other things being equal, +// AmbientLights (for instance) are less important than +// DirectionalLights. +//////////////////////////////////////////////////////////////////// +int Spotlight:: +get_class_priority() const { + return (int)CP_spot_priority; +} + //////////////////////////////////////////////////////////////////// // Function: Spotlight::bind // Access: Public, Virtual diff --git a/panda/src/pgraph/spotlight.h b/panda/src/pgraph/spotlight.h index 6a4fb6f5a8..518afd902c 100644 --- a/panda/src/pgraph/spotlight.h +++ b/panda/src/pgraph/spotlight.h @@ -65,6 +65,8 @@ PUBLISHED: INLINE const LVecBase3f &get_attenuation() const; INLINE void set_attenuation(const LVecBase3f &attenuation); + virtual int get_class_priority() const; + static PT(Texture) make_spot(int pixel_width, float full_radius, Colorf &fg, Colorf &bg); diff --git a/panda/src/pgraph/textureAttrib.cxx b/panda/src/pgraph/textureAttrib.cxx index d44d6c18ba..87103d8768 100644 --- a/panda/src/pgraph/textureAttrib.cxx +++ b/panda/src/pgraph/textureAttrib.cxx @@ -30,7 +30,7 @@ TypeHandle TextureAttrib::_type_handle; // This STL Function object is used in filter_to_max(), below, to sort // a list of TextureStages in reverse order by priority and, within -// prioirty, in order by sort. +// priority, in order by sort. class CompareTextureStagePriorities { public: bool operator ()(const TextureStage *a, const TextureStage *b) const { @@ -778,7 +778,7 @@ fillin(DatagramIterator &scan, BamReader *manager) { // Function: TextureAttrib::sort_on_stages // Access: Private // Description: Sorts the list of stages so that they are listed in -// render order. +// render order. Also clears the _filtered map. //////////////////////////////////////////////////////////////////// void TextureAttrib:: sort_on_stages() {