diff --git a/panda/src/display/graphicsStateGuardian.I b/panda/src/display/graphicsStateGuardian.I index c140ed9fc8..2418325544 100644 --- a/panda/src/display/graphicsStateGuardian.I +++ b/panda/src/display/graphicsStateGuardian.I @@ -28,6 +28,17 @@ LightInfo() { _next_enabled = false; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::ClipPlaneInfo::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE GraphicsStateGuardian::ClipPlaneInfo:: +ClipPlaneInfo() { + _enabled = false; + _next_enabled = false; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::is_closed @@ -340,3 +351,15 @@ get_light(int light_id) const { nassertr(light_id >= 0 && light_id < (int)_light_info.size(), (Light *)NULL); return _light_info[light_id]._light; } + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::get_clip_plane +// Access: Protected +// Description: Returns the PlaneNode object that is bound to the +// indicated id, or NULL if no PlaneNode is bound. +//////////////////////////////////////////////////////////////////// +INLINE PlaneNode *GraphicsStateGuardian:: +get_clip_plane(int plane_id) const { + nassertr(plane_id >= 0 && plane_id < (int)_clip_plane_info.size(), (PlaneNode *)NULL); + return _clip_plane_info[plane_id]._plane; +} diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index c48fd8d863..cf294556a1 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -30,7 +30,9 @@ #include "colorWriteAttrib.h" #include "textureAttrib.h" #include "lightAttrib.h" +#include "clipPlaneAttrib.h" #include "light.h" +#include "planeNode.h" #include "ambientLight.h" #include "clockObject.h" @@ -152,8 +154,10 @@ reset() { _scene_graph_color_stale = false; _vertex_colors_enabled = true; _lighting_enabled = false; - _lighting_enabled_this_frame = false; + + _clip_planes_enabled = false; + _clip_planes_enabled_this_frame = false; } //////////////////////////////////////////////////////////////////// @@ -432,6 +436,21 @@ begin_frame() { _lighting_enabled_this_frame = false; } + // Ditto for the clipping planes. + if (_clip_planes_enabled_this_frame) { + for (int i = 0; i < (int)_clip_plane_info.size(); i++) { + if (_clip_plane_info[i]._enabled) { + enable_clip_plane(i, false); + _clip_plane_info[i]._enabled = false; + } + _clip_plane_info[i]._plane = (PlaneNode *)NULL; + } + + modify_state(get_unclipped_state()); + + _clip_planes_enabled_this_frame = false; + } + #ifdef DO_PSTATS // For Pstats to track our current texture memory usage, we have to // reset the set of current textures each frame. @@ -689,7 +708,7 @@ issue_color(const ColorAttrib *attrib) { // 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_light() is called to prepare the next +// use), slot_new_light() is called to prepare the next // sequential light id. // // It will call apply_light() each time a light is @@ -861,6 +880,125 @@ issue_color_blend(const ColorBlendAttrib *attrib) { set_blend_mode(_color_write_mode, _color_blend_mode, _transparency_mode); } +//////////////////////////////////////////////////////////////////// +// 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. +//////////////////////////////////////////////////////////////////// +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++) { + _clip_plane_info[i]._next_enabled = false; + } + + bool any_bound = false; + + int num_enabled = 0; + int num_planes = attrib->get_num_planes(); + if (attrib->get_operation() == ClipPlaneAttrib::O_remove) { + num_planes = 0; + } + for (int li = 0; li < num_planes; li++) { + PlaneNode *plane = attrib->get_plane(li); + nassertv(plane != (PlaneNode *)NULL); + + num_enabled++; + + // Planeing should be enabled before we apply any planes. + enable_clip_planes(true); + _clip_planes_enabled = true; + _clip_planes_enabled_this_frame = true; + + // 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++) { + 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. + cur_plane_id = -2; + enable_clip_plane(i, true); + _clip_plane_info[i]._enabled = true; + _clip_plane_info[i]._next_enabled = true; + break; + } + } + + // See if there are any unbound plane ids + if (cur_plane_id == -1) { + for (i = 0; i < max_planes; i++) { + if (_clip_plane_info[i]._plane == (PlaneNode *)NULL) { + _clip_plane_info[i]._plane = plane; + cur_plane_id = i; + break; + } + } + } + + // 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_plane(_clip_plane_info[i]._plane)) { + _clip_plane_info[i]._plane = plane; + cur_plane_id = i; + break; + } + } + } + + // 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; + _clip_plane_info.push_back(ClipPlaneInfo()); + max_planes++; + nassertv(max_planes == (int)_clip_plane_info.size()); + } + } + + if (cur_plane_id >= 0) { + enable_clip_plane(cur_plane_id, true); + _clip_plane_info[cur_plane_id]._enabled = true; + _clip_plane_info[cur_plane_id]._next_enabled = true; + + if (!any_bound) { + begin_bind_clip_planes(); + any_bound = true; + } + + // This is the first time this frame that this plane has been + // bound to this particular id. + bind_clip_plane(plane, cur_plane_id); + + } else if (cur_plane_id == -1) { + gsg_cat.warning() + << "Failed to bind " << *plane << " to id.\n"; + } + } + + // Disable all unused planes + for (i = 0; i < max_planes; i++) { + if (!_clip_plane_info[i]._next_enabled) { + enable_clip_plane(i, false); + _clip_plane_info[i]._enabled = false; + } + } + + // If no planes were enabled, disable clip planes in general. + if (num_enabled == 0) { + enable_clip_planes(false); + _clip_planes_enabled = false; + } + + if (any_bound) { + end_bind_clip_planes(); + } +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::bind_light // Access: Public, Virtual @@ -979,6 +1117,90 @@ 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 +// Description: Intended to be overridden by a derived class to +// enable or disable the use of clipping planes overall. +// This is called by issue_clip_plane() according to +// whether any planes are in use or not. +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +enable_clip_planes(bool enable) { +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::enable_clip_plane +// Access: Protected, Virtual +// Description: Intended to be overridden by a derived class to +// enable the indicated plane id. A specific PlaneNode +// will already have been bound to this id via +// bind_clip_plane(). +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +enable_clip_plane(int plane_id, bool enable) { +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::begin_bind_clip_planes +// Access: Protected, Virtual +// Description: Called immediately before bind_clip_plane() is called, +// this is intended to provide the derived class a hook +// in which to set up some state (like transform) that +// might apply to several planes. +// +// The sequence is: begin_bind_clip_planes() will be +// called, then one or more bind_clip_plane() calls, +// then end_bind_clip_planes(). +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +begin_bind_clip_planes() { +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::bind_clip_plane +// Access: Public, Virtual +// Description: Called the first time a particular clipping plane has been +// bound to a given id within a frame, this should set +// up the associated hardware (or API) clipping plane +// with the plane's properties. +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +bind_clip_plane(PlaneNode *plane, int plane_id) { +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::end_bind_clip_planes +// Access: Protected, Virtual +// Description: Called after before bind_clip_plane() has been called one +// or more times (but before any geometry is issued or +// additional state is changed), this is intended to +// clean up any temporary changes to the state that may +// have been made by begin_bind_clip_planes(). +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +end_bind_clip_planes() { +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::set_blend_mode // Access: Protected, Virtual @@ -1248,6 +1470,20 @@ get_unlit_state() { return state; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::get_unclipped_state +// Access: Protected, Static +// Description: +//////////////////////////////////////////////////////////////////// +CPT(RenderState) GraphicsStateGuardian:: +get_unclipped_state() { + static CPT(RenderState) state = NULL; + if (state == (const RenderState *)NULL) { + state = RenderState::make(ClipPlaneAttrib::make_all_off()); + } + return state; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::get_untextured_state // Access: Protected, Static diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index 752dab077c..5698b2b077 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -35,6 +35,7 @@ #include "transformState.h" #include "renderState.h" #include "light.h" +#include "planeNode.h" #include "colorWriteAttrib.h" #include "colorBlendAttrib.h" #include "transparencyAttrib.h" @@ -148,6 +149,7 @@ public: virtual void issue_color_write(const ColorWriteAttrib *attrib); virtual void issue_transparency(const TransparencyAttrib *attrib); 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); @@ -162,6 +164,14 @@ protected: virtual void begin_bind_lights(); virtual void end_bind_lights(); + INLINE PlaneNode *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(); + virtual void bind_clip_plane(PlaneNode *plane, int pane_id); + virtual void end_bind_clip_planes(); + virtual void set_blend_mode(ColorWriteAttrib::Mode color_write_mode, ColorBlendAttrib::Mode color_blend_mode, TransparencyAttrib::Mode transparency_mode); @@ -199,6 +209,7 @@ protected: #endif static CPT(RenderState) get_unlit_state(); + static CPT(RenderState) get_unclipped_state(); static CPT(RenderState) get_untextured_state(); protected: @@ -233,6 +244,7 @@ protected: bool _scene_graph_color_stale; bool _vertex_colors_enabled; bool _lighting_enabled; + bool _clip_planes_enabled; enum ColorTransform { CT_offset = 0x01, @@ -285,6 +297,17 @@ private: pvector _light_info; bool _lighting_enabled_this_frame; + class ClipPlaneInfo { + public: + INLINE ClipPlaneInfo(); + PT(PlaneNode) _plane; + bool _enabled; + bool _next_enabled; + }; + + pvector _clip_plane_info; + bool _clip_planes_enabled_this_frame; + // NOTE: on win32 another DLL (e.g. libpandadx.dll) cannot access // these sets directly due to exported template issue typedef pset Textures; diff --git a/panda/src/glgsg/glGraphicsStateGuardian.I b/panda/src/glgsg/glGraphicsStateGuardian.I index ce1f49aff1..44f1ff631d 100644 --- a/panda/src/glgsg/glGraphicsStateGuardian.I +++ b/panda/src/glgsg/glGraphicsStateGuardian.I @@ -795,31 +795,6 @@ enable_scissor(bool val) } } -//////////////////////////////////////////////////////////////////// -// Function: GLGraphicsStateGuardian::enable_clip_plane -// Access: -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void GLGraphicsStateGuardian:: -enable_clip_plane(int clip_plane, bool val) { - if (_clip_plane_enabled[clip_plane] != val) { - _clip_plane_enabled[clip_plane] = val; - if (val) { -#ifdef GSG_VERBOSE - glgsg_cat.debug() - << "glEnable(GL_CLIP_PLANE_" << clip_plane << ")" << endl; -#endif - glEnable(get_clip_plane_id(clip_plane)); - } else { -#ifdef GSG_VERBOSE - glgsg_cat.debug() - << "glDisable(GL_CLIP_PLANE_" << clip_plane << ")" << endl; -#endif - glDisable(get_clip_plane_id(clip_plane)); - } - } -} - //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::enable_multisample_alpha_one // Access: diff --git a/panda/src/glgsg/glGraphicsStateGuardian.cxx b/panda/src/glgsg/glGraphicsStateGuardian.cxx index 7491117078..f3cac98e14 100644 --- a/panda/src/glgsg/glGraphicsStateGuardian.cxx +++ b/panda/src/glgsg/glGraphicsStateGuardian.cxx @@ -34,6 +34,7 @@ #include "directionalLight.h" #include "pointLight.h" #include "spotlight.h" +#include "planeNode.h" #include "GL/glu.h" #include "textureAttrib.h" #include "lightAttrib.h" @@ -128,9 +129,6 @@ issue_transformed_color_gl(const Geom *geom, Geom::ColorIterator &citerator, //////////////////////////////////////////////////////////////////// GLGraphicsStateGuardian:: GLGraphicsStateGuardian(GraphicsWindow *win) : GraphicsStateGuardian(win) { - _clip_plane_enabled = (bool *)NULL; - _cur_clip_plane_enabled = (bool *)NULL; - reset(); } @@ -256,18 +254,10 @@ reset() { glGetIntegerv(GL_MAX_LIGHTS, &max_lights); _max_lights = max_lights; - // Set up the clip plane id map + // Count the max number of clipping planes GLint max_clip_planes; glGetIntegerv(GL_MAX_CLIP_PLANES, &max_clip_planes); _max_clip_planes = max_clip_planes; - _available_clip_plane_ids = PTA(PlaneNode*)::empty_array(_max_clip_planes); - _clip_plane_enabled = new bool[_max_clip_planes]; - _cur_clip_plane_enabled = new bool[_max_clip_planes]; - int i; - for (i = 0; i < _max_clip_planes; i++) { - _available_clip_plane_ids[i] = NULL; - _clip_plane_enabled[i] = false; - } _current_projection_mat = LMatrix4f::ident_mat(); _projection_mat_stack_count = 0; @@ -3452,6 +3442,106 @@ end_bind_lights() { glPopMatrix(); } +//////////////////////////////////////////////////////////////////// +// 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 GLGraphicsStateGuardian:: +slot_new_clip_plane(int plane_id) { + return (plane_id < _max_clip_planes); +} + +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::enable_clip_plane +// Access: Protected, Virtual +// Description: Intended to be overridden by a derived class to +// enable the indicated clip_plane id. A specific +// PlaneNode will already have been bound to this id via +// bind_clip_plane(). +//////////////////////////////////////////////////////////////////// +void GLGraphicsStateGuardian:: +enable_clip_plane(int plane_id, bool enable) { + if (enable) { + glEnable(get_clip_plane_id(plane_id)); + } else { + glDisable(get_clip_plane_id(plane_id)); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::begin_bind_clip_planes +// Access: Protected, Virtual +// Description: Called immediately before bind_clip_plane() is called, +// this is intended to provide the derived class a hook +// in which to set up some state (like transform) that +// might apply to several clip_planes. +// +// The sequence is: begin_bind_clip_planes() will be called, +// then one or more bind_clip_plane() calls, then +// end_bind_clip_planes(). +//////////////////////////////////////////////////////////////////// +void GLGraphicsStateGuardian:: +begin_bind_clip_planes() { + // We need to temporarily load a new matrix so we can define the + // clip_plane in a known coordinate system. We pick the transform of the + // root. (Alternatively, we could leave the current transform where + // it is and compute the clip_plane position relative to that transform + // instead of relative to the root, by composing with the matrix + // computed by _transform->invert_compose(render_transform). But I + // think loading a completely new matrix is simpler.) + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadMatrixf(_scene_setup->get_render_transform()->get_mat().get_data()); +} + +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::bind_clip_plane +// Access: Protected, Virtual +// Description: Called the first time a particular clip_plane has been +// bound to a given id within a frame, this should set +// up the associated hardware clip_plane with the clip_plane's +// properties. +//////////////////////////////////////////////////////////////////// +void GLGraphicsStateGuardian:: +bind_clip_plane(PlaneNode *plane, int plane_id) { + GLenum id = get_clip_plane_id(plane_id); + + NodePath plane_np(plane); + const LMatrix4f &plane_mat = plane_np.get_mat(_scene_setup->get_scene_root()); + Planef xformed_plane = plane->get_plane() * plane_mat; + + Planed double_plane(xformed_plane._a, xformed_plane._b, + xformed_plane._c, xformed_plane._d); + glClipPlane(id, double_plane.get_data()); + + report_errors(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::end_bind_clip_planes +// Access: Protected, Virtual +// Description: Called after before bind_clip_plane() has been called one +// or more times (but before any geometry is issued or +// additional state is changed), this is intended to +// clean up any temporary changes to the state that may +// have been made by begin_bind_clip_planes(). +//////////////////////////////////////////////////////////////////// +void GLGraphicsStateGuardian:: +end_bind_clip_planes() { + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +} + //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::set_blend_mode // Access: Protected, Virtual @@ -3562,14 +3652,6 @@ set_blend_mode(ColorWriteAttrib::Mode color_write_mode, //////////////////////////////////////////////////////////////////// void GLGraphicsStateGuardian:: free_pointers() { - if (_clip_plane_enabled != (bool *)NULL) { - delete[] _clip_plane_enabled; - _clip_plane_enabled = (bool *)NULL; - } - if (_cur_clip_plane_enabled != (bool *)NULL) { - delete[] _cur_clip_plane_enabled; - _cur_clip_plane_enabled = (bool *)NULL; - } } //////////////////////////////////////////////////////////////////// @@ -3859,10 +3941,6 @@ dump_state(void) dump << "\t\t" << "GL_TEXTURE_2D " << _texturing_enabled << " " << (bool)glIsEnabled(GL_TEXTURE_2D) << "\n"; dump << "\t\t" << "GL_DITHER " << _dither_enabled << " " << (bool)glIsEnabled(GL_DITHER) << "\n"; dump << "\t\t" << "GL_STENCIL_TEST " << " " << (bool)glIsEnabled(GL_STENCIL_TEST) << "\n"; - for(i = 0; i < _max_clip_planes; i++) - { - dump << "\t\t\t\t" << "GL_CLIP_PLANE" << i << " " << _clip_plane_enabled[i] << " " << (bool)glIsEnabled(GL_CLIP_PLANE0+i) << "\n"; - } dump << "\t\t" << "GL_BLEND " << _blend_enabled << " " << (bool)glIsEnabled(GL_BLEND) << "\n"; dump << "\t\t" << "GL_DEPTH_TEST " << _depth_test_enabled << " " << (bool)glIsEnabled(GL_DEPTH_TEST) << "\n"; dump << "\t\t" << "GL_FOG " << _fog_enabled << " " << (bool)glIsEnabled(GL_FOG) << "\n"; diff --git a/panda/src/glgsg/glGraphicsStateGuardian.h b/panda/src/glgsg/glGraphicsStateGuardian.h index 0a64d5f0d8..749677189e 100644 --- a/panda/src/glgsg/glGraphicsStateGuardian.h +++ b/panda/src/glgsg/glGraphicsStateGuardian.h @@ -123,7 +123,6 @@ public: virtual void issue_depth_offset(const DepthOffsetAttrib *attrib); // virtual void issue_tex_gen(const TexGenAttrib *attrib); // virtual void issue_stencil(const StencilAttrib *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); @@ -153,6 +152,12 @@ protected: 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(PlaneNode *plane, int plane_id); + virtual void end_bind_clip_planes(); + virtual void set_blend_mode(ColorWriteAttrib::Mode color_write_mode, ColorBlendAttrib::Mode color_blend_mode, TransparencyAttrib::Mode transparency_mode); @@ -202,7 +207,6 @@ protected: INLINE void enable_scissor(bool val); INLINE void enable_dither(bool val); INLINE void enable_stencil_test(bool val); - INLINE void enable_clip_plane(int clip_plane, bool val); INLINE void enable_multisample_alpha_one(bool val); INLINE void enable_multisample_alpha_mask(bool val); INLINE void enable_blend(bool val); @@ -307,16 +311,11 @@ protected: int _decal_level; int _max_lights; + int _max_clip_planes; LMatrix4f _current_projection_mat; int _projection_mat_stack_count; - int _max_clip_planes; - PTA(PlaneNode *)_available_clip_plane_ids; // pPlaneNode[_max_clip_planes] - bool *_clip_plane_enabled; // bool[_max_clip_planes] - bool *_cur_clip_plane_enabled; // bool[_max_clip_planes] - int _cur_clip_plane_id; - CPT(DisplayRegion) _actual_display_region; int _pass_number; diff --git a/panda/src/mathutil/plane_src.I b/panda/src/mathutil/plane_src.I index 0a32cfbd3f..e1ca6989ab 100644 --- a/panda/src/mathutil/plane_src.I +++ b/panda/src/mathutil/plane_src.I @@ -73,7 +73,8 @@ FLOATNAME(Plane)(const FLOATNAME(LPoint3) &a, const FLOATNAME(LPoint3) &b, // a point within the plane. //////////////////////////////////////////////////////////////////// INLINE_MATHUTIL FLOATNAME(Plane):: -FLOATNAME(Plane)(const FLOATNAME(LVector3) &normal, const FLOATNAME(LPoint3) &point) { +FLOATNAME(Plane)(const FLOATNAME(LVector3) &normal, + const FLOATNAME(LPoint3) &point) { FLOATNAME(LVector3) p = normalize(normal); _a = p[0]; @@ -82,6 +83,21 @@ FLOATNAME(Plane)(const FLOATNAME(LVector3) &normal, const FLOATNAME(LPoint3) &po _d = -dot(p, point); } +//////////////////////////////////////////////////////////////////// +// Function: Plane::Constructor +// Access: Public +// Description: Constructs a plane given the four terms of the plane +// equation. +//////////////////////////////////////////////////////////////////// +INLINE_MATHUTIL FLOATNAME(Plane):: +FLOATNAME(Plane)(FLOATTYPE a, FLOATTYPE b, FLOATTYPE c, FLOATTYPE d) : + _a(a), + _b(b), + _c(c), + _d(d) +{ +} + //////////////////////////////////////////////////////////////////// // Function: Plane::Operator = // Access: Public @@ -197,6 +213,30 @@ intersects_line(FLOATTYPE &t, return true; } +//////////////////////////////////////////////////////////////////// +// Function: Plane::get_data +// Access: Public +// Description: Returns the address of the first of the four data +// elements in the plane equation. The remaining +// elements occupy the next positions consecutively in +// memory. +//////////////////////////////////////////////////////////////////// +INLINE_MATHUTIL const FLOATTYPE *FLOATNAME(Plane):: +get_data() const { + return &_a; +} + +//////////////////////////////////////////////////////////////////// +// Function: Plane::get_num_components +// Access: Public +// Description: Returns the number of elements in the plane equation, +// four. +//////////////////////////////////////////////////////////////////// +INLINE_MATHUTIL int FLOATNAME(Plane):: +get_num_components() const { + return 4; +} + //////////////////////////////////////////////////////////////////// // Function: Plane::output // Access: Public @@ -223,12 +263,18 @@ write(ostream &out, int indent_level) const { // Description: //////////////////////////////////////////////////////////////////// INLINE_MATHUTIL void FLOATNAME(Plane):: -write_datagram(Datagram &dest) -{ +write_datagram(Datagram &dest) const { +#if FLOATTOKEN == 'f' dest.add_float32(_a); dest.add_float32(_b); dest.add_float32(_c); dest.add_float32(_d); +#else + dest.add_float64(_a); + dest.add_float64(_b); + dest.add_float64(_c); + dest.add_float64(_d); +#endif } //////////////////////////////////////////////////////////////////// @@ -237,10 +283,16 @@ write_datagram(Datagram &dest) // Description: //////////////////////////////////////////////////////////////////// INLINE_MATHUTIL void FLOATNAME(Plane):: -read_datagram(DatagramIterator &source) -{ +read_datagram(DatagramIterator &source) { +#if FLOATTOKEN == 'f' _a = source.get_float32(); _b = source.get_float32(); _c = source.get_float32(); _d = source.get_float32(); +#else + _a = source.get_float64(); + _b = source.get_float64(); + _c = source.get_float64(); + _d = source.get_float64(); +#endif } diff --git a/panda/src/mathutil/plane_src.h b/panda/src/mathutil/plane_src.h index 505b7a4948..4104ac8e15 100644 --- a/panda/src/mathutil/plane_src.h +++ b/panda/src/mathutil/plane_src.h @@ -24,10 +24,13 @@ class EXPCL_PANDA FLOATNAME(Plane) { PUBLISHED: INLINE_MATHUTIL FLOATNAME(Plane)(void); INLINE_MATHUTIL FLOATNAME(Plane)(const FLOATNAME(Plane) ©); - INLINE_MATHUTIL FLOATNAME(Plane)(const FLOATNAME(LPoint3) &a, const FLOATNAME(LPoint3) &b, - const FLOATNAME(LPoint3) &c); + INLINE_MATHUTIL FLOATNAME(Plane)(const FLOATNAME(LPoint3) &a, + const FLOATNAME(LPoint3) &b, + const FLOATNAME(LPoint3) &c); INLINE_MATHUTIL FLOATNAME(Plane)(const FLOATNAME(LVector3) &normal, - const FLOATNAME(LPoint3) &point); + const FLOATNAME(LPoint3) &point); + INLINE_MATHUTIL FLOATNAME(Plane)(FLOATTYPE a, FLOATTYPE b, + FLOATTYPE c, FLOATTYPE d); INLINE_MATHUTIL FLOATNAME(Plane)& operator = (const FLOATNAME(Plane)& copy); @@ -47,11 +50,14 @@ PUBLISHED: const FLOATNAME(LPoint3) &from, const FLOATNAME(LVector3) &delta) const; + INLINE_MATHUTIL const FLOATTYPE *get_data() const; + INLINE_MATHUTIL int get_num_components() const; + INLINE_MATHUTIL void output(ostream &out) const; INLINE_MATHUTIL void write(ostream &out, int indent_level = 0) const; public: - INLINE_MATHUTIL void write_datagram(Datagram &dest); + INLINE_MATHUTIL void write_datagram(Datagram &dest) const; INLINE_MATHUTIL void read_datagram(DatagramIterator &source); public: diff --git a/panda/src/pgraph/Sources.pp b/panda/src/pgraph/Sources.pp index a9fce1e39e..25391a4998 100644 --- a/panda/src/pgraph/Sources.pp +++ b/panda/src/pgraph/Sources.pp @@ -14,6 +14,7 @@ billboardEffect.I billboardEffect.h \ binCullHandler.I binCullHandler.h \ camera.I camera.h \ + clipPlaneAttrib.I clipPlaneAttrib.h \ colorAttrib.I colorAttrib.h \ colorBlendAttrib.I colorBlendAttrib.h \ colorScaleAttrib.I colorScaleAttrib.h \ @@ -64,6 +65,7 @@ nodePathComponent.I nodePathComponent.h \ nodePathLerps.h \ pandaNode.I pandaNode.h \ + planeNode.I planeNode.h \ pointLight.I pointLight.h \ renderAttrib.I renderAttrib.h \ renderEffect.I renderEffect.h \ @@ -93,6 +95,7 @@ billboardEffect.cxx \ binCullHandler.cxx \ camera.cxx \ + clipPlaneAttrib.cxx \ colorAttrib.cxx \ colorBlendAttrib.cxx \ colorScaleAttrib.cxx \ @@ -143,6 +146,7 @@ nodePathComponent.cxx \ nodePathLerps.cxx \ pandaNode.cxx \ + planeNode.cxx \ pointLight.cxx \ renderAttrib.cxx \ renderEffect.cxx \ @@ -171,6 +175,7 @@ billboardEffect.I billboardEffect.h \ binCullHandler.I binCullHandler.h \ camera.I camera.h \ + clipPlaneAttrib.I clipPlaneAttrib.h \ colorAttrib.I colorAttrib.h \ colorBlendAttrib.I colorBlendAttrib.h \ colorScaleAttrib.I colorScaleAttrib.h \ @@ -218,6 +223,7 @@ nodePathComponent.I nodePathComponent.h \ nodePathLerps.h \ pandaNode.I pandaNode.h \ + planeNode.I planeNode.h \ pointLight.I pointLight.h \ renderAttrib.I renderAttrib.h \ renderEffect.I renderEffect.h \ diff --git a/panda/src/pgraph/clipPlaneAttrib.I b/panda/src/pgraph/clipPlaneAttrib.I new file mode 100644 index 0000000000..e60ac51a34 --- /dev/null +++ b/panda/src/pgraph/clipPlaneAttrib.I @@ -0,0 +1,119 @@ +// Filename: clipPlaneAttrib.I +// Created by: drose (11Jul02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::Constructor +// Access: Private +// Description: Use ClipPlaneAttrib::make() to construct a new +// ClipPlaneAttrib object. +//////////////////////////////////////////////////////////////////// +INLINE ClipPlaneAttrib:: +ClipPlaneAttrib() { + _operation = O_set; +} + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::get_operation +// Access: Published +// Description: Returns the basic operation type of the ClipPlaneAttrib. +// If this is O_set, the planes listed here completely +// replace any planes that were already on. If this is +// O_add, the planes here are added to the set of of +// planes that were already on, and if O_remove, the +// planes here are removed from the set of planes that +// were on. +//////////////////////////////////////////////////////////////////// +INLINE ClipPlaneAttrib::Operation ClipPlaneAttrib:: +get_operation() const { + return _operation; +} + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::get_num_planes +// Access: Published +// Description: Returns the number of planes listed in the attribute. +//////////////////////////////////////////////////////////////////// +INLINE int ClipPlaneAttrib:: +get_num_planes() const { + return _planes.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::get_plane +// Access: Published +// Description: Returns the nth planes listed in the attribute. +//////////////////////////////////////////////////////////////////// +INLINE PlaneNode *ClipPlaneAttrib:: +get_plane(int n) const { + nassertr(n >= 0 && n < (int)_planes.size(), (PlaneNode *)NULL); + return _planes[n]; +} + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::add_plane +// Access: Published +// Description: Returns a new ClipPlaneAttrib, just like this one, but +// with the indicated plane added to the list of planes. +//////////////////////////////////////////////////////////////////// +INLINE CPT(RenderAttrib) ClipPlaneAttrib:: +add_plane(PlaneNode *plane) const { + if (_operation == O_remove) { + return compose(make(O_remove, plane)); + } else { + return compose(make(O_add, plane)); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::remove_plane +// Access: Published +// Description: Returns a new ClipPlaneAttrib, just like this one, but +// with the indicated plane removed from the list of +// planes. +//////////////////////////////////////////////////////////////////// +INLINE CPT(RenderAttrib) ClipPlaneAttrib:: +remove_plane(PlaneNode *plane) const { + if (_operation == O_remove) { + return compose(make(O_add, plane)); + } else { + return compose(make(O_remove, plane)); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::is_identity +// Access: Published +// Description: Returns true if this is an identity attrib: it does +// not change the set of planes in use. +//////////////////////////////////////////////////////////////////// +INLINE bool ClipPlaneAttrib:: +is_identity() const { + return _operation != O_set && _planes.empty(); +} + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::is_all_off +// Access: Published +// Description: Returns true if this attrib turns off all planes and +// turns none on. +//////////////////////////////////////////////////////////////////// +INLINE bool ClipPlaneAttrib:: +is_all_off() const { + return _operation == O_set && _planes.empty(); +} diff --git a/panda/src/pgraph/clipPlaneAttrib.cxx b/panda/src/pgraph/clipPlaneAttrib.cxx new file mode 100644 index 0000000000..7817d9973c --- /dev/null +++ b/panda/src/pgraph/clipPlaneAttrib.cxx @@ -0,0 +1,489 @@ +// Filename: clipPlaneAttrib.cxx +// Created by: drose (11Jul02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "clipPlaneAttrib.h" +#include "pandaNode.h" +#include "graphicsStateGuardianBase.h" +#include "bamReader.h" +#include "bamWriter.h" +#include "datagram.h" +#include "datagramIterator.h" + +TypeHandle ClipPlaneAttrib::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::make_all_off +// Access: Published, Static +// Description: Constructs a new ClipPlaneAttrib object that turns off +// all planes (and hence disables planeing). +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) ClipPlaneAttrib:: +make_all_off() { + ClipPlaneAttrib *attrib = new ClipPlaneAttrib; + attrib->_operation = O_set; + return return_new(attrib); +} + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::make +// Access: Published, Static +// Description: Constructs a new ClipPlaneAttrib object that turns on (or +// off, according to op) the indicate plane(s). +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) ClipPlaneAttrib:: +make(ClipPlaneAttrib::Operation op, PlaneNode *plane) { + ClipPlaneAttrib *attrib = new ClipPlaneAttrib; + attrib->_operation = op; + attrib->_planes.push_back(plane); + return return_new(attrib); +} + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::make +// Access: Published, Static +// Description: Constructs a new ClipPlaneAttrib object that turns on (or +// off, according to op) the indicate plane(s). +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) ClipPlaneAttrib:: +make(ClipPlaneAttrib::Operation op, PlaneNode *plane1, PlaneNode *plane2) { + ClipPlaneAttrib *attrib = new ClipPlaneAttrib; + attrib->_operation = op; + attrib->_planes.push_back(plane1); + attrib->_planes.push_back(plane2); + + attrib->_planes.sort(); + return return_new(attrib); +} + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::make +// Access: Published, Static +// Description: Constructs a new ClipPlaneAttrib object that turns on (or +// off, according to op) the indicate plane(s). +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) ClipPlaneAttrib:: +make(ClipPlaneAttrib::Operation op, PlaneNode *plane1, PlaneNode *plane2, + PlaneNode *plane3) { + ClipPlaneAttrib *attrib = new ClipPlaneAttrib; + attrib->_operation = op; + attrib->_planes.push_back(plane1); + attrib->_planes.push_back(plane2); + attrib->_planes.push_back(plane3); + + attrib->_planes.sort(); + return return_new(attrib); +} + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::make +// Access: Published, Static +// Description: Constructs a new ClipPlaneAttrib object that turns on (or +// off, according to op) the indicate plane(s). +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) ClipPlaneAttrib:: +make(ClipPlaneAttrib::Operation op, PlaneNode *plane1, PlaneNode *plane2, + PlaneNode *plane3, PlaneNode *plane4) { + ClipPlaneAttrib *attrib = new ClipPlaneAttrib; + attrib->_operation = op; + attrib->_planes.push_back(plane1); + attrib->_planes.push_back(plane2); + attrib->_planes.push_back(plane3); + attrib->_planes.push_back(plane4); + + attrib->_planes.sort(); + return return_new(attrib); +} + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::has_plane +// Access: Published +// Description: Returns true if the indicated plane is listed in the +// attrib, false otherwise. +//////////////////////////////////////////////////////////////////// +bool ClipPlaneAttrib:: +has_plane(PlaneNode *plane) const { + return _planes.find(plane) != _planes.end(); +} + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::issue +// Access: Public, Virtual +// Description: Calls the appropriate method on the indicated GSG +// to issue the graphics commands appropriate to the +// given attribute. This is normally called +// (indirectly) only from +// GraphicsStateGuardian::set_state() or modify_state(). +//////////////////////////////////////////////////////////////////// +void ClipPlaneAttrib:: +issue(GraphicsStateGuardianBase *gsg) const { + gsg->issue_clip_plane(this); +} + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::output +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void ClipPlaneAttrib:: +output(ostream &out) const { + out << get_type() << ":"; + if (_operation == O_set && _planes.empty()) { + out << "all off"; + } else { + switch (_operation) { + case O_set: + out << "set"; + break; + case O_add: + out << "add"; + break; + case O_remove: + out << "remove"; + break; + } + + Planes::const_iterator li; + for (li = _planes.begin(); li != _planes.end(); ++li) { + PlaneNode *plane = (*li); + out << " " << *plane; + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::compare_to_impl +// Access: Protected, Virtual +// Description: Intended to be overridden by derived ClipPlaneAttrib +// types to return a unique number indicating whether +// this ClipPlaneAttrib is equivalent to the other one. +// +// This should return 0 if the two ClipPlaneAttrib objects +// are equivalent, a number less than zero if this one +// should be sorted before the other one, and a number +// greater than zero otherwise. +// +// This will only be called with two ClipPlaneAttrib +// objects whose get_type() functions return the same. +//////////////////////////////////////////////////////////////////// +int ClipPlaneAttrib:: +compare_to_impl(const RenderAttrib *other) const { + const ClipPlaneAttrib *ta; + DCAST_INTO_R(ta, other, 0); + + if (_operation != ta->_operation) { + return (int)_operation - (int)ta->_operation; + } + + Planes::const_iterator li = _planes.begin(); + Planes::const_iterator oli = ta->_planes.begin(); + + while (li != _planes.end() && oli != ta->_planes.end()) { + PlaneNode *plane = (*li); + PlaneNode *other_plane = (*oli); + + if (plane != other_plane) { + return plane < other_plane ? -1 : 1; + } + + ++li; + ++oli; + } + + if (li != _planes.end()) { + return 1; + } + if (oli != ta->_planes.end()) { + return -1; + } + + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::compose_impl +// Access: Protected, Virtual +// Description: Intended to be overridden by derived RenderAttrib +// types to specify how two consecutive RenderAttrib +// objects of the same type interact. +// +// This should return the result of applying the other +// RenderAttrib to a node in the scene graph below this +// RenderAttrib, which was already applied. In most +// cases, the result is the same as the other +// RenderAttrib (that is, a subsequent RenderAttrib +// completely replaces the preceding one). On the other +// hand, some kinds of RenderAttrib (for instance, +// ColorTransformAttrib) might combine in meaningful +// ways. +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) ClipPlaneAttrib:: +compose_impl(const RenderAttrib *other) const { + const ClipPlaneAttrib *ta; + DCAST_INTO_R(ta, other, 0); + + if (ta->_operation == O_set) { + // If the other type is O_set, it doesn't matter what we are. + return ta; + } + + if (_operation == ta->_operation) { + // If the operation types match, the composition is simply the + // union. + return do_add(ta, _operation); + + } else if (ta->_operation == O_remove) { + // If the other operation type is remove, and our type is add or + // set, then remove. + return do_remove(ta, _operation); + + } else if (_operation == O_remove) { + // If our type is remove, then the other one wins. + return ta; + + } else { + // Otherwise, the result is the union. + return do_add(ta, _operation); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::invert_compose_impl +// Access: Protected, Virtual +// Description: Intended to be overridden by derived RenderAttrib +// types to specify how two consecutive RenderAttrib +// objects of the same type interact. +// +// See invert_compose() and compose_impl(). +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) ClipPlaneAttrib:: +invert_compose_impl(const RenderAttrib *other) const { + // I think in this case the other attrib always wins. Maybe this + // needs a bit more thought. It's hard to imagine that it's even + // important to compute this properly. + return other; +} + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::make_default_impl +// Access: Protected, Virtual +// Description: Intended to be overridden by derived ClipPlaneAttrib +// types to specify what the default property for a +// ClipPlaneAttrib of this type should be. +// +// This should return a newly-allocated ClipPlaneAttrib of +// the same type that corresponds to whatever the +// standard default for this kind of ClipPlaneAttrib is. +//////////////////////////////////////////////////////////////////// +RenderAttrib *ClipPlaneAttrib:: +make_default_impl() const { + return new ClipPlaneAttrib; +} + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::do_add +// Access: Private +// Description: Returns a new ClipPlaneAttrib that represents all the +// planes of this attrib, with those of the other one +// added in. +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) ClipPlaneAttrib:: +do_add(const ClipPlaneAttrib *other, ClipPlaneAttrib::Operation op) const { + Planes::const_iterator ai = _planes.begin(); + Planes::const_iterator bi = other->_planes.begin(); + + // Create a new ClipPlaneAttrib that will hold the result. + ClipPlaneAttrib *new_attrib = new ClipPlaneAttrib; + new_attrib->_operation = op; + back_insert_iterator result = + back_inserter(new_attrib->_planes); + + while (ai != _planes.end() && bi != other->_planes.end()) { + if ((*ai) < (*bi)) { + // Here is a plane that we have in the original, which is not + // present in the secondary. + *result = *ai; + ++ai; + ++result; + } else if ((*bi) < (*ai)) { + // Here is a new plane we have in the secondary, that was not + // present in the original. + *result = *bi; + ++bi; + ++result; + } else { + // Here is a plane we have in both. + *result = *ai; + ++ai; + ++bi; + ++result; + } + } + + while (ai != _planes.end()) { + *result = *ai; + ++ai; + ++result; + } + + while (bi != other->_planes.end()) { + *result = *bi; + ++bi; + ++result; + } + + return return_new(new_attrib); +} + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::do_remove +// Access: Private +// Description: Returns a new ClipPlaneAttrib that represents all the +// planes of this attrib, with those of the other one +// removed. +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) ClipPlaneAttrib:: +do_remove(const ClipPlaneAttrib *other, ClipPlaneAttrib::Operation op) const { + Planes::const_iterator ai = _planes.begin(); + Planes::const_iterator bi = other->_planes.begin(); + + // Create a new ClipPlaneAttrib that will hold the result. + ClipPlaneAttrib *new_attrib = new ClipPlaneAttrib; + new_attrib->_operation = op; + back_insert_iterator result = + back_inserter(new_attrib->_planes); + + while (ai != _planes.end() && bi != other->_planes.end()) { + if ((*ai) < (*bi)) { + // Here is a plane that we have in the original, which is + // not present in the secondary. Keep it. + *result = *ai; + ++ai; + ++result; + } else if ((*bi) < (*ai)) { + // Here is a new plane we have in the secondary, that was + // not present in the original. Ignore it. + ++bi; + } else { + // Here is a plane we have in both. Drop it. + ++ai; + ++bi; + } + } + + while (ai != _planes.end()) { + *result = *ai; + ++ai; + ++result; + } + + return return_new(new_attrib); +} + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// ClipPlaneAttrib. +//////////////////////////////////////////////////////////////////// +void ClipPlaneAttrib:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void ClipPlaneAttrib:: +write_datagram(BamWriter *manager, Datagram &dg) { + RenderAttrib::write_datagram(manager, dg); + + dg.add_int8((int)_operation); + PN_uint16 num_planes = _planes.size(); + nassertv(num_planes == _planes.size()); + dg.add_uint16(num_planes); + + Planes::const_iterator li; + for (li = _planes.begin(); li != _planes.end(); ++li) { + PlaneNode *plane = (*li); + manager->write_pointer(dg, plane); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::complete_pointers +// Access: Public, Virtual +// Description: Receives an array of pointers, one for each time +// manager->read_pointer() was called in fillin(). +// Returns the number of pointers processed. +//////////////////////////////////////////////////////////////////// +int ClipPlaneAttrib:: +complete_pointers(TypedWritable **p_list, BamReader *manager) { + int pi = RenderAttrib::complete_pointers(p_list, manager); + + Planes::iterator li; + for (li = _planes.begin(); li != _planes.end(); ++li) { + PlaneNode *node; + DCAST_INTO_R(node, p_list[pi++], pi); + (*li) = node; + } + + return pi; +} + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type ClipPlaneAttrib is encountered +// in the Bam file. It should create the ClipPlaneAttrib +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *ClipPlaneAttrib:: +make_from_bam(const FactoryParams ¶ms) { + ClipPlaneAttrib *attrib = new ClipPlaneAttrib; + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + attrib->fillin(scan, manager); + + return attrib; +} + +//////////////////////////////////////////////////////////////////// +// Function: ClipPlaneAttrib::fillin +// Access: Protected +// Description: This internal function is called by make_from_bam to +// read in all of the relevant data from the BamFile for +// the new ClipPlaneAttrib. +//////////////////////////////////////////////////////////////////// +void ClipPlaneAttrib:: +fillin(DatagramIterator &scan, BamReader *manager) { + RenderAttrib::fillin(scan, manager); + + _operation = (Operation)scan.get_int8(); + int num_planes = scan.get_uint16(); + + for (int i = 0; i < num_planes; i++) { + manager->read_pointer(scan); + _planes.push_back(NULL); + } +} diff --git a/panda/src/pgraph/clipPlaneAttrib.h b/panda/src/pgraph/clipPlaneAttrib.h new file mode 100644 index 0000000000..b6d5f950d0 --- /dev/null +++ b/panda/src/pgraph/clipPlaneAttrib.h @@ -0,0 +1,120 @@ +// Filename: clipPlaneAttrib.h +// Created by: drose (11Jul02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#ifndef CLIPPINGPLANEATTRIB_H +#define CLIPPINGPLANEATTRIB_H + +#include "pandabase.h" + +#include "planeNode.h" +#include "renderAttrib.h" +#include "ordered_vector.h" + +//////////////////////////////////////////////////////////////////// +// Class : ClipPlaneAttrib +// Description : This functions similarly to a LightAttrib. It +// indicates the set of clipping planes that modify the +// geometry at this level and below. A ClipPlaneAttrib +// can either add planes or remove planes from the total +// set of clipping planes in effect. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA ClipPlaneAttrib : public RenderAttrib { +private: + INLINE ClipPlaneAttrib(); + +PUBLISHED: + enum Operation { + O_set, + O_add, + O_remove + }; + + static CPT(RenderAttrib) make_all_off(); + static CPT(RenderAttrib) make(Operation op, + PlaneNode *plane); + static CPT(RenderAttrib) make(Operation op, + PlaneNode *plane1, PlaneNode *plane2); + static CPT(RenderAttrib) make(Operation op, + PlaneNode *plane1, PlaneNode *plane2, + PlaneNode *plane3); + static CPT(RenderAttrib) make(Operation op, + PlaneNode *plane1, PlaneNode *plane2, + PlaneNode *plane3, PlaneNode *plane4); + + INLINE Operation get_operation() const; + + INLINE int get_num_planes() const; + INLINE PlaneNode *get_plane(int n) const; + bool has_plane(PlaneNode *plane) const; + + INLINE CPT(RenderAttrib) add_plane(PlaneNode *plane) const; + INLINE CPT(RenderAttrib) remove_plane(PlaneNode *plane) const; + + INLINE bool is_identity() const; + INLINE bool is_all_off() const; + +public: + virtual void issue(GraphicsStateGuardianBase *gsg) const; + virtual void output(ostream &out) const; + +protected: + virtual int compare_to_impl(const RenderAttrib *other) const; + virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const; + virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const; + virtual RenderAttrib *make_default_impl() const; + +private: + CPT(RenderAttrib) do_add(const ClipPlaneAttrib *other, Operation op) const; + CPT(RenderAttrib) do_remove(const ClipPlaneAttrib *other, Operation op) const; + +private: + Operation _operation; + typedef ov_set< PT(PlaneNode) > Planes; + Planes _planes; + +public: + static void register_with_read_factory(); + virtual void write_datagram(BamWriter *manager, Datagram &dg); + virtual int complete_pointers(TypedWritable **plist, BamReader *manager); + +protected: + static TypedWritable *make_from_bam(const FactoryParams ¶ms); + void fillin(DatagramIterator &scan, BamReader *manager); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + RenderAttrib::init_type(); + register_type(_type_handle, "ClipPlaneAttrib", + RenderAttrib::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "clipPlaneAttrib.I" + +#endif + diff --git a/panda/src/pgraph/config_pgraph.cxx b/panda/src/pgraph/config_pgraph.cxx index a1023ccc54..fde866f396 100644 --- a/panda/src/pgraph/config_pgraph.cxx +++ b/panda/src/pgraph/config_pgraph.cxx @@ -22,6 +22,7 @@ #include "ambientLight.h" #include "billboardEffect.h" #include "camera.h" +#include "clipPlaneAttrib.h" #include "colorAttrib.h" #include "colorBlendAttrib.h" #include "colorScaleAttrib.h" @@ -58,6 +59,7 @@ #include "nodePath.h" #include "nodePathComponent.h" #include "pandaNode.h" +#include "planeNode.h" #include "pointLight.h" #include "renderAttrib.h" #include "renderEffect.h" @@ -160,6 +162,7 @@ init_libpgraph() { AmbientLight::init_type(); BillboardEffect::init_type(); Camera::init_type(); + ClipPlaneAttrib::init_type(); ColorAttrib::init_type(); ColorBlendAttrib::init_type(); ColorScaleAttrib::init_type(); @@ -195,6 +198,7 @@ init_libpgraph() { NodePath::init_type(); NodePathComponent::init_type(); PandaNode::init_type(); + PlaneNode::init_type(); PointLight::init_type(); RenderAttrib::init_type(); RenderEffect::init_type(); @@ -225,6 +229,7 @@ init_libpgraph() { AmbientLight::register_with_read_factory(); BillboardEffect::register_with_read_factory(); Camera::register_with_read_factory(); + ClipPlaneAttrib::register_with_read_factory(); ColorAttrib::register_with_read_factory(); ColorBlendAttrib::register_with_read_factory(); ColorScaleAttrib::register_with_read_factory(); @@ -246,6 +251,7 @@ init_libpgraph() { ModelNode::register_with_read_factory(); ModelRoot::register_with_read_factory(); PandaNode::register_with_read_factory(); + PlaneNode::register_with_read_factory(); PointLight::register_with_read_factory(); RenderEffects::register_with_read_factory(); RenderModeAttrib::register_with_read_factory(); diff --git a/panda/src/pgraph/pgraph_composite1.cxx b/panda/src/pgraph/pgraph_composite1.cxx index f871b7d0ea..8be701a9d6 100644 --- a/panda/src/pgraph/pgraph_composite1.cxx +++ b/panda/src/pgraph/pgraph_composite1.cxx @@ -3,6 +3,7 @@ #include "billboardEffect.cxx" #include "binCullHandler.cxx" #include "camera.cxx" +#include "clipPlaneAttrib.cxx" #include "colorAttrib.cxx" #include "colorBlendAttrib.cxx" #include "colorScaleAttrib.cxx" diff --git a/panda/src/pgraph/pgraph_composite2.cxx b/panda/src/pgraph/pgraph_composite2.cxx index de94f88044..3ca976c16d 100644 --- a/panda/src/pgraph/pgraph_composite2.cxx +++ b/panda/src/pgraph/pgraph_composite2.cxx @@ -16,6 +16,7 @@ #include "nodePathComponent.cxx" #include "nodePathLerps.cxx" #include "pandaNode.cxx" +#include "planeNode.cxx" #include "pointLight.cxx" #include "renderAttrib.cxx" #include "renderEffect.cxx" diff --git a/panda/src/pgraph/planeNode.I b/panda/src/pgraph/planeNode.I new file mode 100644 index 0000000000..e731805f32 --- /dev/null +++ b/panda/src/pgraph/planeNode.I @@ -0,0 +1,63 @@ +// Filename: planeNode.I +// Created by: drose (11Jul02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: PlaneNode::CData::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE PlaneNode::CData:: +CData() { + // The default plane (perpendicular to the Z-axis) is used until + // another one is specified explicitly. +} + +//////////////////////////////////////////////////////////////////// +// Function: PlaneNode::CData::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE PlaneNode::CData:: +CData(const PlaneNode::CData ©) : + _plane(copy._plane) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: set_plane +// Access: Public +// Description: Sets the particular plane represented by the +// PlaneNode. +//////////////////////////////////////////////////////////////////// +INLINE void PlaneNode:: +set_plane(const Planef &plane) { + CDWriter cdata(_cycler); + cdata->_plane = plane; +} + +//////////////////////////////////////////////////////////////////// +// Function: get_plane +// Access: Public +// Description: Returns the plane represented by the PlaneNode. +//////////////////////////////////////////////////////////////////// +INLINE const Planef &PlaneNode:: +get_plane() const { + CDReader cdata(_cycler); + return cdata->_plane; +} diff --git a/panda/src/pgraph/planeNode.cxx b/panda/src/pgraph/planeNode.cxx new file mode 100644 index 0000000000..7a94b60698 --- /dev/null +++ b/panda/src/pgraph/planeNode.cxx @@ -0,0 +1,187 @@ +// Filename: planeNode.cxx +// Created by: drose (11Jul02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "planeNode.h" +#include "geometricBoundingVolume.h" +#include "bamWriter.h" +#include "bamReader.h" +#include "datagram.h" +#include "datagramIterator.h" + +TypeHandle PlaneNode::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: PlaneNode::CData::make_copy +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +CycleData *PlaneNode::CData:: +make_copy() const { + return new CData(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: PlaneNode::CData::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void PlaneNode::CData:: +write_datagram(BamWriter *, Datagram &dg) const { + _plane.write_datagram(dg); +} + +//////////////////////////////////////////////////////////////////// +// Function: PlaneNode::CData::fillin +// Access: Public, Virtual +// Description: This internal function is called by make_from_bam to +// read in all of the relevant data from the BamFile for +// the new Light. +//////////////////////////////////////////////////////////////////// +void PlaneNode::CData:: +fillin(DatagramIterator &scan, BamReader *) { + _plane.read_datagram(scan); +} + +//////////////////////////////////////////////////////////////////// +// Function: PlaneNode::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +PlaneNode:: +PlaneNode(const string &name) : + PandaNode(name) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: PlaneNode::Copy Constructor +// Access: Protected +// Description: +//////////////////////////////////////////////////////////////////// +PlaneNode:: +PlaneNode(const PlaneNode ©) : + PandaNode(copy), + _cycler(copy._cycler) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: PlaneNode::make_copy +// Access: Public, Virtual +// Description: Returns a newly-allocated Node that is a shallow copy +// of this one. It will be a different Node pointer, +// but its internal data may or may not be shared with +// that of the original Node. +//////////////////////////////////////////////////////////////////// +PandaNode *PlaneNode:: +make_copy() const { + return new PlaneNode(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: PlaneNode::xform +// Access: Public, Virtual +// Description: Transforms the contents of this PandaNode by the +// indicated matrix, if it means anything to do so. For +// most kinds of PandaNodes, this does nothing. +//////////////////////////////////////////////////////////////////// +void PlaneNode:: +xform(const LMatrix4f &mat) { + PandaNode::xform(mat); + CDWriter cdata(_cycler); + cdata->_plane = cdata->_plane * mat; +} + +//////////////////////////////////////////////////////////////////// +// Function: PlaneNode::output +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void PlaneNode:: +output(ostream &out) const { + PandaNode::output(out); + out << " " << get_plane(); +} + +//////////////////////////////////////////////////////////////////// +// Function: PlaneNode::write +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void PlaneNode:: +write(ostream &out, int indent_level) const { + PandaNode::write(out, indent_level); + get_plane().write(out, indent_level + 2); +} + +//////////////////////////////////////////////////////////////////// +// Function: PlaneNode::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// PlaneNode. +//////////////////////////////////////////////////////////////////// +void PlaneNode:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: PlaneNode::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void PlaneNode:: +write_datagram(BamWriter *manager, Datagram &dg) { + PandaNode::write_datagram(manager, dg); + manager->write_cdata(dg, _cycler); +} + +//////////////////////////////////////////////////////////////////// +// Function: PlaneNode::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type PlaneNode is encountered +// in the Bam file. It should create the PlaneNode +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *PlaneNode:: +make_from_bam(const FactoryParams ¶ms) { + PlaneNode *node = new PlaneNode(""); + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + node->fillin(scan, manager); + + return node; +} + +//////////////////////////////////////////////////////////////////// +// Function: PlaneNode::fillin +// Access: Protected +// Description: This internal function is called by make_from_bam to +// read in all of the relevant data from the BamFile for +// the new PlaneNode. +//////////////////////////////////////////////////////////////////// +void PlaneNode:: +fillin(DatagramIterator &scan, BamReader *manager) { + PandaNode::fillin(scan, manager); + manager->read_cdata(scan, _cycler); +} diff --git a/panda/src/pgraph/planeNode.h b/panda/src/pgraph/planeNode.h new file mode 100644 index 0000000000..4c1167e0a7 --- /dev/null +++ b/panda/src/pgraph/planeNode.h @@ -0,0 +1,96 @@ +// Filename: planeNode.h +// Created by: drose (11Jul02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#ifndef PLANENODE_H +#define PLANENODE_H + +#include "pandabase.h" + +#include "plane.h" +#include "pandaNode.h" + +//////////////////////////////////////////////////////////////////// +// Class : PlaneNode +// Description : A node that contains a plane. This is most often +// used as a clipping plane, but it can serve other +// purposes as well; whenever a plane is needed to be +// defined in some coordinate space in the world. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA PlaneNode : public PandaNode { +PUBLISHED: + PlaneNode(const string &name); + +protected: + PlaneNode(const PlaneNode ©); +public: + virtual void output(ostream &out) const; + virtual void write(ostream &out, int indent_level = 0) const; + + virtual PandaNode *make_copy() const; + virtual void xform(const LMatrix4f &mat); + +PUBLISHED: + INLINE void set_plane(const Planef &plane); + INLINE const Planef &get_plane() const; + +private: + // This is the data that must be cycled between pipeline stages. + class EXPCL_PANDA CData : public CycleData { + public: + INLINE CData(); + INLINE CData(const CData ©); + virtual CycleData *make_copy() const; + virtual void write_datagram(BamWriter *manager, Datagram &dg) const; + virtual void fillin(DatagramIterator &scan, BamReader *manager); + + Planef _plane; + }; + + PipelineCycler _cycler; + typedef CycleDataReader CDReader; + typedef CycleDataWriter CDWriter; + +public: + static void register_with_read_factory(); + virtual void write_datagram(BamWriter *manager, Datagram &dg); + +protected: + static TypedWritable *make_from_bam(const FactoryParams ¶ms); + void fillin(DatagramIterator &scan, BamReader *manager); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + PandaNode::init_type(); + register_type(_type_handle, "PlaneNode", + PandaNode::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "planeNode.I" + +#endif