diff --git a/panda/src/display/Sources.pp b/panda/src/display/Sources.pp index 0322c46e6c..82beb4d09c 100644 --- a/panda/src/display/Sources.pp +++ b/panda/src/display/Sources.pp @@ -13,7 +13,6 @@ config_display.h displayRegion.I displayRegion.h \ displayRegionStack.I \ displayRegionStack.h \ - drawCullHandler.h drawCullHandler.I \ frameBufferStack.I frameBufferStack.h \ geomContext.I geomContext.h geomNodeContext.I geomNodeContext.h \ graphicsChannel.I graphicsChannel.h \ @@ -33,7 +32,6 @@ #define INCLUDED_SOURCES \ config_display.cxx displayRegion.cxx \ - drawCullHandler.cxx \ geomContext.cxx geomNodeContext.cxx graphicsChannel.cxx \ graphicsEngine.cxx \ graphicsLayer.cxx graphicsPipe.cxx graphicsStateGuardian.cxx \ @@ -46,7 +44,6 @@ config_display.h \ displayRegion.I displayRegion.h displayRegionStack.I \ displayRegionStack.h \ - drawCullHandler.h drawCullHandler.I \ frameBufferStack.I frameBufferStack.h \ geomContext.I geomContext.h geomNodeContext.I geomNodeContext.h \ graphicsChannel.I graphicsChannel.h \ diff --git a/panda/src/display/display_composite1.cxx b/panda/src/display/display_composite1.cxx index 9ac9f76253..3cad8174c9 100644 --- a/panda/src/display/display_composite1.cxx +++ b/panda/src/display/display_composite1.cxx @@ -1,6 +1,5 @@ #include "displayRegion.cxx" -#include "drawCullHandler.cxx" #include "geomContext.cxx" #include "geomNodeContext.cxx" #include "graphicsChannel.cxx" diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 9760e08a07..00a8ecc6c5 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -22,6 +22,9 @@ #include "textureContext.h" #include "renderBuffer.h" #include "colorAttrib.h" +#include "renderState.h" +#include "depthWriteAttrib.h" +#include "colorWriteAttrib.h" #include "clockObject.h" #include "geomNode.h" @@ -892,6 +895,101 @@ void GraphicsStateGuardian:: end_decal(GeomNode *) { } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::polygon_offset_decals +// Access: Public, Virtual +// Description: Returns true if this GSG can implement decals using a +// PolygonOffsetAttrib, or false if that is unreliable +// and the three-step rendering process should be used +// instead. +//////////////////////////////////////////////////////////////////// +bool GraphicsStateGuardian:: +polygon_offset_decals() { + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::begin_decal_base_first +// Access: Public, Virtual +// Description: Called during draw to begin a three-step rendering +// phase to draw decals. The first step, +// begin_decal_base_first(), is called prior to drawing the +// base geometry. It should set up whatever internal +// state is appropriate, as well as returning a +// RenderState object that should be applied to the base +// geometry for rendering. +//////////////////////////////////////////////////////////////////// +CPT(RenderState) GraphicsStateGuardian:: +begin_decal_base_first() { + // Turn off writing the depth buffer to render the base geometry. + static CPT(RenderState) decal_base_first; + if (decal_base_first == (const RenderState *)NULL) { + decal_base_first = RenderState::make + (DepthWriteAttrib::make(DepthWriteAttrib::M_off)); + } + return decal_base_first; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::begin_decal_nested +// Access: Public, Virtual +// Description: Called during draw to begin a three-step rendering +// phase to draw decals. The second step, +// begin_decal_nested(), is called after drawing the +// base geometry and prior to drawing any of the nested +// decal geometry that is to be applied to the base +// geometry. +//////////////////////////////////////////////////////////////////// +CPT(RenderState) GraphicsStateGuardian:: +begin_decal_nested() { + // We keep the depth buffer off during this operation, although + // perhaps it doesn't matter so much here. + static CPT(RenderState) decal_nested; + if (decal_nested == (const RenderState *)NULL) { + decal_nested = RenderState::make + (DepthWriteAttrib::make(DepthWriteAttrib::M_off)); + } + return decal_nested; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::begin_decal_base_second +// Access: Public, Virtual +// Description: Called during draw to begin a three-step rendering +// phase to draw decals. The third step, +// begin_decal_base_second(), is called after drawing the +// base geometry and the nested decal geometry, and +// prior to drawing the base geometry one more time (if +// needed). +// +// It should return a RenderState object appropriate for +// rendering the base geometry the second time, or NULL +// if it is not necessary to re-render the base +// geometry. +//////////////////////////////////////////////////////////////////// +CPT(RenderState) GraphicsStateGuardian:: +begin_decal_base_second() { + // Now let the depth buffer go back on, but turn off writing the + // color buffer to render the base geometry after the second pass. + static CPT(RenderState) decal_base_second; + if (decal_base_second == (const RenderState *)NULL) { + decal_base_second = RenderState::make + (ColorWriteAttrib::make(ColorWriteAttrib::M_off)); + } + return decal_base_second; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::finish_decal +// Access: Public, Virtual +// Description: Called during draw to clean up after decals are +// finished. +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +finish_decal() { + // No need to do anything special here. +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::get_internal_coordinate_system // Access: Public, Virtual diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index 117c631d4f..15b5c02c59 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -135,6 +135,12 @@ public: virtual void begin_decal(GeomNode *base_geom, AllTransitionsWrapper &attrib); virtual void end_decal(GeomNode *base_geom); + virtual bool polygon_offset_decals(); + virtual CPT(RenderState) begin_decal_base_first(); + virtual CPT(RenderState) begin_decal_nested(); + virtual CPT(RenderState) begin_decal_base_second(); + virtual void finish_decal(); + virtual void reset(); // *** QP diff --git a/panda/src/egg2pg/qpeggLoader.cxx b/panda/src/egg2pg/qpeggLoader.cxx index 5ce8502219..2aac9222f3 100644 --- a/panda/src/egg2pg/qpeggLoader.cxx +++ b/panda/src/egg2pg/qpeggLoader.cxx @@ -28,6 +28,7 @@ #include "cullFaceAttrib.h" #include "cullBinAttrib.h" #include "transparencyAttrib.h" +#include "decalAttrib.h" #include "qpgeomNode.h" #include "string_utils.h" #include "eggPrimitive.h" @@ -39,6 +40,7 @@ #include "eggPolygon.h" #include "eggBin.h" #include "eggTable.h" +#include "nodeChain.h" #include #include @@ -123,16 +125,13 @@ build_graph() { make_node(&_data, _root); _builder.qpbuild(); - /* - reset_directs(); + // reset_directs(); reparent_decals(); - apply_deferred_arcs(_root); - */ + // apply_deferred_arcs(_root); } -/* //////////////////////////////////////////////////////////////////// // Function: qpEggLoader::reparent_decals // Access: Public @@ -145,38 +144,34 @@ void qpEggLoader:: reparent_decals() { Decals::const_iterator di; for (di = _decals.begin(); di != _decals.end(); ++di) { - RenderRelation *arc = (*di); - nassertv(arc != (RenderRelation *)NULL); - PandaNode *node = DCAST(PandaNode, arc->get_child()); + PandaNode *node = (*di); nassertv(node != (PandaNode *)NULL); - // First, search for the GeomNode. - GeomNode *geom = NULL; - int num_children = - node->get_num_children(RenderRelation::get_class_type()); - for (int i = 0; i < num_children; i++) { - NodeRelation *child_arc = - node->get_child(RenderRelation::get_class_type(), i); - nassertv(child_arc != (NodeRelation *)NULL); - Node *child = child_arc->get_child(); - nassertv(child != (Node *)NULL); + // The NodeChain interface is best for this. + NodeChain parent(node); - if (child->is_of_type(GeomNode::get_class_type())) { - if (geom != (GeomNode *)NULL) { + // First, search for the GeomNode. + NodeChain geom_parent; + int num_children = parent.get_num_children(); + for (int i = 0; i < num_children; i++) { + NodeChain child = parent.get_child(i); + + if (child.node()->is_of_type(qpGeomNode::get_class_type())) { + if (!geom_parent.is_empty()) { // Oops, too many GeomNodes. egg2pg_cat.error() - << "Decal onto " << node->get_name() - << " uses base geometry with multiple states.\n"; + << "Decal onto " << parent.node()->get_name() + << " uses base geometry with multiple GeomNodes.\n"; _error = true; } - DCAST_INTO_V(geom, child); + geom_parent = child; } } - if (geom == (GeomNode *)NULL) { + if (geom_parent.is_empty()) { // No children were GeomNodes. egg2pg_cat.error() - << "Ignoring decal onto " << node->get_name() + << "Ignoring decal onto " << parent.node()->get_name() << "; no geometry within group.\n"; _error = true; } else { @@ -185,23 +180,21 @@ reparent_decals() { // list. int i = 0; while (i < num_children) { - NodeRelation *child_arc = - node->get_child(RenderRelation::get_class_type(), i); - nassertv(child_arc != (NodeRelation *)NULL); - Node *child = child_arc->get_child(); - nassertv(child != (Node *)NULL); + NodeChain child = parent.get_child(i); - if (child->is_of_type(GeomNode::get_class_type())) { + if (child.node()->is_of_type(qpGeomNode::get_class_type())) { i++; } else { - child_arc->change_parent(geom); + child.reparent_to(geom_parent); num_children--; } } + + // Finally, set the DecalAttrib on the base geometry. + geom_parent.node()->set_attrib(DecalAttrib::make()); } } } -*/ /* //////////////////////////////////////////////////////////////////// @@ -1516,7 +1509,6 @@ create_group_arc(EggGroup *egg_group, PandaNode *parent, PandaNode *node) { break; } - /* if (egg_group->get_decal_flag()) { if (egg_ignore_decals) { egg2pg_cat.error() @@ -1528,12 +1520,8 @@ create_group_arc(EggGroup *egg_group, PandaNode *parent, PandaNode *node) { // descendant groups will be decaled onto the geometry within // this group. This means we'll need to reparent things a bit // afterward. - _decals.insert(arc); - - // We'll also set up the DecalTransition now. - arc->set_transition(new DecalTransition); + _decals.insert(node); } - */ /* if (egg_group->get_direct_flag()) { diff --git a/panda/src/egg2pg/qpeggLoader.h b/panda/src/egg2pg/qpeggLoader.h index ca7d617262..9ad2cdabec 100644 --- a/panda/src/egg2pg/qpeggLoader.h +++ b/panda/src/egg2pg/qpeggLoader.h @@ -139,10 +139,10 @@ private: Materials _materials_bface; */ - /* typedef pset Decals; Decals _decals; + /* typedef pset Directs; Directs _directs; diff --git a/panda/src/glgsg/glGraphicsStateGuardian.I b/panda/src/glgsg/glGraphicsStateGuardian.I index adb5c58ead..fb70675bc7 100644 --- a/panda/src/glgsg/glGraphicsStateGuardian.I +++ b/panda/src/glgsg/glGraphicsStateGuardian.I @@ -473,23 +473,6 @@ call_glBlendFunc(GLenum sfunc, GLenum dfunc) { } } -//////////////////////////////////////////////////////////////////// -// Function: GLGraphicsStateGuardian::call_glDepthMask -// Access: -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void GLGraphicsStateGuardian:: -call_glDepthMask(GLboolean mask) { - if (_depth_mask != mask) { - _depth_mask = mask; -#ifdef GSG_VERBOSE - glgsg_cat.debug() - << "glDepthMask(" << (int)mask << ")" << endl; -#endif - glDepthMask(mask); - } -} - //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::call_glFogMode // Access: diff --git a/panda/src/glgsg/glGraphicsStateGuardian.cxx b/panda/src/glgsg/glGraphicsStateGuardian.cxx index 3de88598bc..fe6bc39867 100644 --- a/panda/src/glgsg/glGraphicsStateGuardian.cxx +++ b/panda/src/glgsg/glGraphicsStateGuardian.cxx @@ -68,6 +68,9 @@ #include "textureAttrib.h" #include "cullFaceAttrib.h" #include "transparencyAttrib.h" +#include "depthTestAttrib.h" +#include "depthWriteAttrib.h" +#include "colorWriteAttrib.h" #include "clockObject.h" #include "string_utils.h" #include "dcast.h" @@ -3143,8 +3146,7 @@ issue_depth_test(const DepthTestTransition *attrib) { void GLGraphicsStateGuardian:: issue_depth_write(const DepthWriteTransition *attrib) { // activate(); - - call_glDepthMask(attrib->is_on()); + glDepthMask(attrib->is_on()); report_errors(); } @@ -3544,6 +3546,55 @@ issue_transparency(const TransparencyAttrib *attrib) { report_errors(); } +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::issue_color_write +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void GLGraphicsStateGuardian:: +issue_color_write(const ColorWriteAttrib *attrib) { + ColorWriteAttrib::Mode mode = attrib->get_mode(); + if (mode == ColorWriteAttrib::M_off) { + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + } else { + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + } + report_errors(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::issue_depth_test +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void GLGraphicsStateGuardian:: +issue_depth_test(const DepthTestAttrib *attrib) { + DepthTestAttrib::Mode mode = attrib->get_mode(); + if (mode == DepthTestAttrib::M_none) { + enable_depth_test(false); + } else { + enable_depth_test(true); + glDepthFunc(get_depth_func_type(mode)); + } + report_errors(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::issue_depth_write +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void GLGraphicsStateGuardian:: +issue_depth_write(const DepthWriteAttrib *attrib) { + DepthWriteAttrib::Mode mode = attrib->get_mode(); + if (mode == DepthWriteAttrib::M_off) { + glDepthMask(GL_FALSE); + } else { + glDepthMask(GL_TRUE); + } + report_errors(); +} + //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::wants_normals // Access: Public, Virtual @@ -3603,7 +3654,7 @@ begin_decal(GeomNode *base_geom, AllTransitionsWrapper &attrib) { } else { // Turn off writing the depth buffer to render the base geometry. - call_glDepthMask(false); + glDepthMask(false); DepthWriteTransition *dwa = new DepthWriteTransition; dwa->set_off(); attrib.set_transition(dwa); @@ -3661,7 +3712,7 @@ end_decal(GeomNode *base_geom) { glPopMatrix(); // Enable the writing to the depth buffer. - call_glDepthMask(true); + glDepthMask(true); // Disable the writing to the color buffer, however we have to // do this. @@ -4360,6 +4411,31 @@ get_depth_func_type(DepthTestProperty::Mode m) const } } +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::get_depth_func_type +// Access: Protected +// Description: Maps from the depth func modes to gl version +//////////////////////////////////////////////////////////////////// +GLenum GLGraphicsStateGuardian:: +get_depth_func_type(DepthTestAttrib::Mode m) const +{ + switch(m) { + case DepthTestAttrib::M_never: return GL_NEVER; + case DepthTestAttrib::M_less: return GL_LESS; + case DepthTestAttrib::M_equal: return GL_EQUAL; + case DepthTestAttrib::M_less_equal: return GL_LEQUAL; + case DepthTestAttrib::M_greater: return GL_GREATER; + case DepthTestAttrib::M_not_equal: return GL_NOTEQUAL; + case DepthTestAttrib::M_greater_equal: return GL_GEQUAL; + case DepthTestAttrib::M_always: return GL_ALWAYS; + + default: + glgsg_cat.error() + << "Invalid DepthTestAttrib::Mode value" << endl; + return GL_LESS; + } +} + //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::get_stencil_func_type // Access: Protected diff --git a/panda/src/glgsg/glGraphicsStateGuardian.h b/panda/src/glgsg/glGraphicsStateGuardian.h index 15a4f9d246..87c55bbd23 100644 --- a/panda/src/glgsg/glGraphicsStateGuardian.h +++ b/panda/src/glgsg/glGraphicsStateGuardian.h @@ -21,19 +21,22 @@ //#define GSG_VERBOSE -#include +#include "pandabase.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "graphicsStateGuardian.h" +#include "geomprimitives.h" +#include "texture.h" +#include "pixelBuffer.h" +#include "displayRegion.h" +#include "material.h" +#include "textureApplyProperty.h" +#include "depthTestProperty.h" +#include "stencilProperty.h" +#include "fog.h" +#include "pt_Light.h" + +#include "depthTestAttrib.h" +#include "pointerToArray.h" #ifdef WIN32_VC // Must include windows.h before gl.h on NT @@ -44,7 +47,6 @@ #include -#include class PlaneNode; class Light; @@ -160,6 +162,9 @@ public: virtual void issue_texture(const TextureAttrib *attrib); virtual void issue_cull_face(const CullFaceAttrib *attrib); virtual void issue_transparency(const TransparencyAttrib *attrib); + virtual void issue_color_write(const ColorWriteAttrib *attrib); + virtual void issue_depth_test(const DepthTestAttrib *attrib); + virtual void issue_depth_write(const DepthWriteAttrib *attrib); virtual bool wants_normals(void) const; virtual bool wants_texcoords(void) const; @@ -212,7 +217,6 @@ protected: INLINE void call_glClipPlane(GLenum plane, const double equation[4]); INLINE void call_glLineWidth(GLfloat width); INLINE void call_glPointSize(GLfloat size); - INLINE void call_glDepthMask(GLboolean mask); INLINE void call_glFogMode(GLint mode); INLINE void call_glFogStart(GLfloat start); INLINE void call_glFogEnd(GLfloat end); @@ -261,6 +265,7 @@ protected: GLenum get_internal_image_format(PixelBuffer::Format format); GLint get_texture_apply_mode_type( TextureApplyProperty::Mode am ) const; GLenum get_depth_func_type(DepthTestProperty::Mode m) const; + GLenum get_depth_func_type(DepthTestAttrib::Mode m) const; GLenum get_stencil_func_type(StencilProperty::Mode m) const; GLenum get_stencil_action_type(StencilProperty::Action a) const; GLenum get_fog_mode_type(Fog::Mode m) const; diff --git a/panda/src/gobj/geom.cxx b/panda/src/gobj/geom.cxx index 37a80e469d..f67679811a 100644 --- a/panda/src/gobj/geom.cxx +++ b/panda/src/gobj/geom.cxx @@ -492,7 +492,9 @@ write(ostream &out, int indent_level) const { //////////////////////////////////////////////////////////////////// void Geom:: output(ostream &out) const { - out << get_type() << " (" << _numprims << ")" + out << get_type() << " (" << _numprims << ")"; + + /* << " v:" << _coords.size() << " n:" << _norms.size() << " c:" << _colors.size() @@ -501,6 +503,7 @@ output(ostream &out) const { << " ni:" << _nindex.size() << " ci:" << _cindex.size() << " ti:" << _tindex.size(); + */ } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gsgbase/graphicsStateGuardianBase.h b/panda/src/gsgbase/graphicsStateGuardianBase.h index cc75cf8a2c..d52ad1d997 100644 --- a/panda/src/gsgbase/graphicsStateGuardianBase.h +++ b/panda/src/gsgbase/graphicsStateGuardianBase.h @@ -89,7 +89,7 @@ class MaterialAttrib; class RenderModeAttrib; class ColorBlendAttrib; class TextureApplyAttrib; -class ColorMaskAttrib; +class ColorWriteAttrib; class DepthTestAttrib; class DepthWriteAttrib; class TexGenAttrib; @@ -156,6 +156,16 @@ public: // coordinate space differently. virtual float compute_distance_to(const LPoint3f &point) const=0; + // These are used to implement decals. If polygon_offset_decals() + // returns true, none of the remaining functions will be called, + // since polygon offsets can be used to implement decals fully (and + // usually faster). + virtual bool polygon_offset_decals()=0; + virtual CPT(RenderState) begin_decal_base_first()=0; + virtual CPT(RenderState) begin_decal_nested()=0; + virtual CPT(RenderState) begin_decal_base_second()=0; + virtual void finish_decal()=0; + // Defined here are some internal interface functions for the // GraphicsStateGuardian. These are here to support // double-dispatching from Geoms and NodeTransitions, and are @@ -238,7 +248,7 @@ public: virtual void issue_render_mode(const RenderModeAttrib *) { } virtual void issue_color_blend(const ColorBlendAttrib *) { } virtual void issue_texture_apply(const TextureApplyAttrib *) { } - virtual void issue_color_mask(const ColorMaskAttrib *) { } + virtual void issue_color_write(const ColorWriteAttrib *) { } virtual void issue_depth_test(const DepthTestAttrib *) { } virtual void issue_depth_write(const DepthWriteAttrib *) { } virtual void issue_tex_gen(const TexGenAttrib *) { } diff --git a/panda/src/pgraph/Sources.pp b/panda/src/pgraph/Sources.pp index 0bbb114915..cc5a56b7a6 100644 --- a/panda/src/pgraph/Sources.pp +++ b/panda/src/pgraph/Sources.pp @@ -10,6 +10,7 @@ binCullHandler.h binCullHandler.I \ qpcamera.h qpcamera.I \ colorAttrib.h colorAttrib.I \ + colorWriteAttrib.h colorWriteAttrib.I \ config_pgraph.h \ cullBin.h cullBin.I \ cullBinAttrib.h cullBinAttrib.I \ @@ -17,9 +18,14 @@ cullBinManager.h cullBinManager.I \ cullBinUnsorted.h cullBinUnsorted.I \ cullFaceAttrib.h cullFaceAttrib.I \ - cullHandler.h \ + cullHandler.h cullHandler.I \ cullResult.h cullResult.I \ qpcullTraverser.h qpcullTraverser.I \ + cullableObject.h cullableObject.I \ + decalAttrib.h decalAttrib.I \ + depthTestAttrib.h depthTestAttrib.I \ + depthWriteAttrib.h depthWriteAttrib.I \ + drawCullHandler.h drawCullHandler.I \ qpgeomNode.h qpgeomNode.I \ qplensNode.h qplensNode.I \ nodeChain.h nodeChain.I \ @@ -37,6 +43,7 @@ binCullHandler.cxx \ qpcamera.cxx \ colorAttrib.cxx \ + colorWriteAttrib.cxx \ config_pgraph.cxx \ cullBin.cxx \ cullBinAttrib.cxx \ @@ -47,6 +54,11 @@ cullHandler.cxx \ cullResult.cxx \ qpcullTraverser.cxx \ + cullableObject.cxx \ + decalAttrib.cxx \ + depthTestAttrib.cxx \ + depthWriteAttrib.cxx \ + drawCullHandler.cxx \ qpgeomNode.cxx \ qplensNode.cxx \ nodeChain.cxx \ @@ -69,6 +81,7 @@ binCullHandler.h binCullHandler.I \ qpcamera.h qpcamera.I \ colorAttrib.h colorAttrib.I \ + colorWriteAttrib.h colorWriteAttrib.I \ config_pgraph.h \ cullBin.h cullBin.I \ cullBinAttrib.h cullBinAttrib.I \ @@ -76,9 +89,14 @@ cullBinManager.h cullBinManager.I \ cullBinUnsorted.h cullBinUnsorted.I \ cullFaceAttrib.h cullFaceAttrib.I \ - cullHandler.h \ + cullHandler.h cullHandler.I \ cullResult.h cullResult.I \ qpcullTraverser.h qpcullTraverser.I \ + cullableObject.h cullableObject.I \ + decalAttrib.h decalAttrib.I \ + depthTestAttrib.h depthTestAttrib.I \ + depthWriteAttrib.h depthWriteAttrib.I \ + drawCullHandler.h drawCullHandler.I \ qpgeomNode.h qpgeomNode.I \ qplensNode.h qplensNode.I \ nodeChain.h nodeChain.I \ diff --git a/panda/src/pgraph/binCullHandler.cxx b/panda/src/pgraph/binCullHandler.cxx index d9d51eb0cf..f8228a8a6f 100644 --- a/panda/src/pgraph/binCullHandler.cxx +++ b/panda/src/pgraph/binCullHandler.cxx @@ -18,16 +18,14 @@ #include "binCullHandler.h" - //////////////////////////////////////////////////////////////////// -// Function: BinCullHandler::record_geom +// Function: BinCullHandler::record_object // Access: Public, Virtual // Description: This callback function is intended to be overridden // by a derived class. This is called as each Geom is // discovered by the CullTraverser. //////////////////////////////////////////////////////////////////// void BinCullHandler:: -record_geom(Geom *geom, const TransformState *transform, - const RenderState *state) { - _cull_result->add_geom(geom, transform, state); +record_object(CullableObject *object) { + _cull_result->add_object(object); } diff --git a/panda/src/pgraph/binCullHandler.h b/panda/src/pgraph/binCullHandler.h index f87916deec..042657ffc0 100644 --- a/panda/src/pgraph/binCullHandler.h +++ b/panda/src/pgraph/binCullHandler.h @@ -35,11 +35,7 @@ class EXPCL_PANDA BinCullHandler : public CullHandler { public: INLINE BinCullHandler(CullResult *cull_result); - // virtual void begin_decal(); - virtual void record_geom(Geom *geom, const TransformState *transform, - const RenderState *state); - // virtual void push_decal(); - // virtual void pop_decal(); + virtual void record_object(CullableObject *object); private: PT(CullResult) _cull_result; diff --git a/panda/src/pgraph/colorWriteAttrib.I b/panda/src/pgraph/colorWriteAttrib.I new file mode 100644 index 0000000000..dda5d0564c --- /dev/null +++ b/panda/src/pgraph/colorWriteAttrib.I @@ -0,0 +1,40 @@ +// Filename: colorWriteAttrib.I +// Created by: drose (04Mar02) +// +//////////////////////////////////////////////////////////////////// +// +// 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: ColorWriteAttrib::Constructor +// Access: Private +// Description: Use ColorWriteAttrib::make() to construct a new +// ColorWriteAttrib object. +//////////////////////////////////////////////////////////////////// +INLINE ColorWriteAttrib:: +ColorWriteAttrib(ColorWriteAttrib::Mode mode) : + _mode(mode) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: ColorWriteAttrib::get_mode +// Access: Published +// Description: Returns the color write mode. +//////////////////////////////////////////////////////////////////// +INLINE ColorWriteAttrib::Mode ColorWriteAttrib:: +get_mode() const { + return _mode; +} diff --git a/panda/src/pgraph/colorWriteAttrib.cxx b/panda/src/pgraph/colorWriteAttrib.cxx new file mode 100644 index 0000000000..ca012fd98c --- /dev/null +++ b/panda/src/pgraph/colorWriteAttrib.cxx @@ -0,0 +1,170 @@ +// Filename: colorWriteAttrib.cxx +// Created by: drose (04Mar02) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "colorWriteAttrib.h" +#include "graphicsStateGuardianBase.h" +#include "dcast.h" +#include "bamReader.h" +#include "bamWriter.h" +#include "datagram.h" +#include "datagramIterator.h" + +TypeHandle ColorWriteAttrib::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: ColorWriteAttrib::make +// Access: Published, Static +// Description: Constructs a new ColorWriteAttrib object that specifies +// how to cull geometry. By Panda convention, vertices +// are ordered counterclockwise when seen from the +// front, so the M_cull_clockwise will cull backfacing +// polygons. +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) ColorWriteAttrib:: +make(ColorWriteAttrib::Mode mode) { + ColorWriteAttrib *attrib = new ColorWriteAttrib(mode); + return return_new(attrib); +} + +//////////////////////////////////////////////////////////////////// +// Function: ColorWriteAttrib::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 ColorWriteAttrib:: +issue(GraphicsStateGuardianBase *gsg) const { + gsg->issue_color_write(this); +} + +//////////////////////////////////////////////////////////////////// +// Function: ColorWriteAttrib::output +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void ColorWriteAttrib:: +output(ostream &out) const { + out << get_type() << ":"; + switch (get_mode()) { + case M_off: + out << "off"; + break; + case M_on: + out << "on"; + break; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: ColorWriteAttrib::compare_to_impl +// Access: Protected, Virtual +// Description: Intended to be overridden by derived ColorWriteAttrib +// types to return a unique number indicating whether +// this ColorWriteAttrib is equivalent to the other one. +// +// This should return 0 if the two ColorWriteAttrib 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 ColorWriteAttrib +// objects whose get_type() functions return the same. +//////////////////////////////////////////////////////////////////// +int ColorWriteAttrib:: +compare_to_impl(const RenderAttrib *other) const { + const ColorWriteAttrib *ta; + DCAST_INTO_R(ta, other, 0); + return (int)_mode - (int)ta->_mode; +} + +//////////////////////////////////////////////////////////////////// +// Function: ColorWriteAttrib::make_default_impl +// Access: Protected, Virtual +// Description: Intended to be overridden by derived ColorWriteAttrib +// types to specify what the default property for a +// ColorWriteAttrib of this type should be. +// +// This should return a newly-allocated ColorWriteAttrib of +// the same type that corresponds to whatever the +// standard default for this kind of ColorWriteAttrib is. +//////////////////////////////////////////////////////////////////// +RenderAttrib *ColorWriteAttrib:: +make_default_impl() const { + return new ColorWriteAttrib; +} + +//////////////////////////////////////////////////////////////////// +// Function: ColorWriteAttrib::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// ColorWriteAttrib. +//////////////////////////////////////////////////////////////////// +void ColorWriteAttrib:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: ColorWriteAttrib::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void ColorWriteAttrib:: +write_datagram(BamWriter *manager, Datagram &dg) { + RenderAttrib::write_datagram(manager, dg); + + dg.add_int8(_mode); +} + +//////////////////////////////////////////////////////////////////// +// Function: ColorWriteAttrib::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type ColorWriteAttrib is encountered +// in the Bam file. It should create the ColorWriteAttrib +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *ColorWriteAttrib:: +make_from_bam(const FactoryParams ¶ms) { + ColorWriteAttrib *attrib = new ColorWriteAttrib; + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + attrib->fillin(scan, manager); + + return attrib; +} + +//////////////////////////////////////////////////////////////////// +// Function: ColorWriteAttrib::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 ColorWriteAttrib. +//////////////////////////////////////////////////////////////////// +void ColorWriteAttrib:: +fillin(DatagramIterator &scan, BamReader *manager) { + RenderAttrib::fillin(scan, manager); + + _mode = (Mode)scan.get_int8(); +} diff --git a/panda/src/pgraph/colorWriteAttrib.h b/panda/src/pgraph/colorWriteAttrib.h new file mode 100644 index 0000000000..239beb2f35 --- /dev/null +++ b/panda/src/pgraph/colorWriteAttrib.h @@ -0,0 +1,88 @@ +// Filename: colorWriteAttrib.h +// Created by: drose (04Mar02) +// +//////////////////////////////////////////////////////////////////// +// +// 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 COLORWRITEATTRIB_H +#define COLORWRITEATTRIB_H + +#include "pandabase.h" + +#include "renderAttrib.h" + +//////////////////////////////////////////////////////////////////// +// Class : ColorWriteAttrib +// Description : Enables or disables writing to the color buffer. +// This is primarily useful for certain special effects +// in which it is important to write to the depth buffer +// without affecting the color buffer. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA ColorWriteAttrib : public RenderAttrib { +PUBLISHED: + enum Mode { + M_off, + M_on + }; + +private: + INLINE ColorWriteAttrib(Mode mode = M_on); + +PUBLISHED: + static CPT(RenderAttrib) make(Mode mode); + + INLINE Mode get_mode() 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 RenderAttrib *make_default_impl() const; + +private: + Mode _mode; + +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() { + RenderAttrib::init_type(); + register_type(_type_handle, "ColorWriteAttrib", + 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 "colorWriteAttrib.I" + +#endif + diff --git a/panda/src/pgraph/config_pgraph.cxx b/panda/src/pgraph/config_pgraph.cxx index b21786097c..d9029e0f7b 100644 --- a/panda/src/pgraph/config_pgraph.cxx +++ b/panda/src/pgraph/config_pgraph.cxx @@ -21,11 +21,16 @@ #include "billboardAttrib.h" #include "qpcamera.h" #include "colorAttrib.h" +#include "colorWriteAttrib.h" #include "cullFaceAttrib.h" #include "cullBin.h" #include "cullBinAttrib.h" #include "cullBinBackToFront.h" #include "cullBinUnsorted.h" +#include "cullableObject.h" +#include "decalAttrib.h" +#include "depthTestAttrib.h" +#include "depthWriteAttrib.h" #include "qpgeomNode.h" #include "qplensNode.h" #include "nodeChain.h" @@ -72,11 +77,16 @@ init_libpgraph() { BillboardAttrib::init_type(); qpCamera::init_type(); ColorAttrib::init_type(); + ColorWriteAttrib::init_type(); CullFaceAttrib::init_type(); CullBin::init_type(); CullBinAttrib::init_type(); CullBinBackToFront::init_type(); CullBinUnsorted::init_type(); + CullableObject::init_type(); + DecalAttrib::init_type(); + DepthTestAttrib::init_type(); + DepthWriteAttrib::init_type(); qpGeomNode::init_type(); qpLensNode::init_type(); NodeChain::init_type(); @@ -91,8 +101,12 @@ init_libpgraph() { BillboardAttrib::register_with_read_factory(); ColorAttrib::register_with_read_factory(); + ColorWriteAttrib::register_with_read_factory(); CullBinAttrib::register_with_read_factory(); CullFaceAttrib::register_with_read_factory(); + DecalAttrib::register_with_read_factory(); + DepthTestAttrib::register_with_read_factory(); + DepthWriteAttrib::register_with_read_factory(); qpGeomNode::register_with_read_factory(); PandaNode::register_with_read_factory(); RenderState::register_with_read_factory(); diff --git a/panda/src/pgraph/cullBin.cxx b/panda/src/pgraph/cullBin.cxx index dbe321ea03..eaa50e1b9a 100644 --- a/panda/src/pgraph/cullBin.cxx +++ b/panda/src/pgraph/cullBin.cxx @@ -21,6 +21,15 @@ TypeHandle CullBin::_type_handle; +//////////////////////////////////////////////////////////////////// +// Function: CullBin::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +CullBin:: +~CullBin() { +} + //////////////////////////////////////////////////////////////////// // Function: CullBin::make_next // Access: Public, Virtual @@ -40,14 +49,13 @@ make_next() const { } //////////////////////////////////////////////////////////////////// -// Function: CullBin::add_geom +// Function: CullBin::add_object // Access: Public, Virtual -// Description: Adds the geom, along with its associated state, to +// Description: Adds a geom, along with its associated state, to // the bin for rendering. //////////////////////////////////////////////////////////////////// void CullBin:: -add_geom(Geom *geom, const TransformState *transform, - const RenderState *state) { +add_object(CullableObject *) { } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgraph/cullBin.h b/panda/src/pgraph/cullBin.h index d7764b2adc..ce5e1b536b 100644 --- a/panda/src/pgraph/cullBin.h +++ b/panda/src/pgraph/cullBin.h @@ -24,9 +24,7 @@ #include "typedReferenceCount.h" #include "pointerTo.h" -class Geom; -class TransformState; -class RenderState; +class CullableObject; class GraphicsStateGuardianBase; //////////////////////////////////////////////////////////////////// @@ -43,11 +41,11 @@ class GraphicsStateGuardianBase; class EXPCL_PANDA CullBin : public TypedReferenceCount { public: INLINE CullBin(GraphicsStateGuardianBase *gsg); + virtual ~CullBin(); virtual PT(CullBin) make_next() const; - virtual void add_geom(Geom *geom, const TransformState *transform, - const RenderState *state)=0; + virtual void add_object(CullableObject *object)=0; virtual void finish_cull(); virtual void draw()=0; diff --git a/panda/src/pgraph/cullBinBackToFront.I b/panda/src/pgraph/cullBinBackToFront.I index 82850b3c1e..c76bd32c09 100644 --- a/panda/src/pgraph/cullBinBackToFront.I +++ b/panda/src/pgraph/cullBinBackToFront.I @@ -18,28 +18,25 @@ //////////////////////////////////////////////////////////////////// -// Function: CullBinBackToFront::GeomData::Constructor +// Function: CullBinBackToFront::ObjectData::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// -INLINE CullBinBackToFront::GeomData:: -GeomData(Geom *geom, const TransformState *transform, - const RenderState *state, float dist) : - _geom(geom), - _transform(transform), - _state(state), +INLINE CullBinBackToFront::ObjectData:: +ObjectData(CullableObject *object, float dist) : + _object(object), _dist(dist) { } //////////////////////////////////////////////////////////////////// -// Function: CullBinBackToFront::GeomData::operator < +// Function: CullBinBackToFront::ObjectData::operator < // Access: Public // Description: Specifies the correct sort ordering for these // objects. //////////////////////////////////////////////////////////////////// -INLINE bool CullBinBackToFront::GeomData:: -operator < (const GeomData &other) const { +INLINE bool CullBinBackToFront::ObjectData:: +operator < (const ObjectData &other) const { return _dist > other._dist; } diff --git a/panda/src/pgraph/cullBinBackToFront.cxx b/panda/src/pgraph/cullBinBackToFront.cxx index 8b4f21dae8..3bae862192 100644 --- a/panda/src/pgraph/cullBinBackToFront.cxx +++ b/panda/src/pgraph/cullBinBackToFront.cxx @@ -19,6 +19,8 @@ #include "cullBinBackToFront.h" #include "graphicsStateGuardianBase.h" #include "geometricBoundingVolume.h" +#include "cullableObject.h" +#include "cullHandler.h" #include @@ -26,16 +28,29 @@ TypeHandle CullBinBackToFront::_type_handle; //////////////////////////////////////////////////////////////////// -// Function: CullBinBackToFront::add_geom +// Function: CullBinBackToFront::Destructor // Access: Public, Virtual -// Description: Adds the geom, along with its associated state, to +// Description: +//////////////////////////////////////////////////////////////////// +CullBinBackToFront:: +~CullBinBackToFront() { + Objects::iterator oi; + for (oi = _objects.begin(); oi != _objects.end(); ++oi) { + CullableObject *object = (*oi)._object; + delete object; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: CullBinBackToFront::add_object +// Access: Public, Virtual +// Description: Adds a geom, along with its associated state, to // the bin for rendering. //////////////////////////////////////////////////////////////////// void CullBinBackToFront:: -add_geom(Geom *geom, const TransformState *transform, - const RenderState *state) { +add_object(CullableObject *object) { // Determine the center of the bounding volume. - const BoundingVolume &volume = geom->get_bound(); + const BoundingVolume &volume = object->_geom->get_bound(); if (!volume.is_empty() && volume.is_of_type(GeometricBoundingVolume::get_class_type())) { @@ -43,12 +58,11 @@ add_geom(Geom *geom, const TransformState *transform, DCAST_INTO_V(gbv, &volume); LPoint3f center = gbv->get_approx_center(); - center = center * transform->get_mat(); + nassertv(object->_transform != (const TransformState *)NULL); + center = center * object->_transform->get_mat(); - // Oops! Don't have compute_distance_to() here yet! - // float distance = gsg->compute_distance_to(center); - float distance = -center[2]; - _geoms.push_back(GeomData(geom, transform, state, distance)); + float distance = _gsg->compute_distance_to(center); + _objects.push_back(ObjectData(object, distance)); } } @@ -63,7 +77,7 @@ add_geom(Geom *geom, const TransformState *transform, //////////////////////////////////////////////////////////////////// void CullBinBackToFront:: finish_cull() { - sort(_geoms.begin(), _geoms.end()); + sort(_objects.begin(), _objects.end()); } //////////////////////////////////////////////////////////////////// @@ -74,11 +88,10 @@ finish_cull() { //////////////////////////////////////////////////////////////////// void CullBinBackToFront:: draw() { - Geoms::iterator gi; - for (gi = _geoms.begin(); gi != _geoms.end(); ++gi) { - GeomData &geom_data = (*gi); - _gsg->set_state_and_transform(geom_data._state, geom_data._transform); - geom_data._geom->draw(_gsg); + Objects::const_iterator oi; + for (oi = _objects.begin(); oi != _objects.end(); ++oi) { + CullableObject *object = (*oi)._object; + CullHandler::draw(object, _gsg); } } diff --git a/panda/src/pgraph/cullBinBackToFront.h b/panda/src/pgraph/cullBinBackToFront.h index dad1127624..3cec82a507 100644 --- a/panda/src/pgraph/cullBinBackToFront.h +++ b/panda/src/pgraph/cullBinBackToFront.h @@ -38,27 +38,24 @@ class EXPCL_PANDA CullBinBackToFront : public CullBin { public: INLINE CullBinBackToFront(GraphicsStateGuardianBase *gsg); + virtual ~CullBinBackToFront(); - virtual void add_geom(Geom *geom, const TransformState *transform, - const RenderState *state); + virtual void add_object(CullableObject *object); virtual void finish_cull(); virtual void draw(); private: - class GeomData { + class ObjectData { public: - INLINE GeomData(Geom *geom, const TransformState *transform, - const RenderState *state, float dist); - INLINE bool operator < (const GeomData &other) const; - - PT(Geom) _geom; - CPT(TransformState) _transform; - CPT(RenderState) _state; + INLINE ObjectData(CullableObject *object, float dist); + INLINE bool operator < (const ObjectData &other) const; + + CullableObject *_object; float _dist; }; - typedef pvector Geoms; - Geoms _geoms; + typedef pvector Objects; + Objects _objects; public: static TypeHandle get_class_type() { diff --git a/panda/src/pgraph/cullBinUnsorted.I b/panda/src/pgraph/cullBinUnsorted.I index 6f4f4c343c..cdb03b0cc0 100644 --- a/panda/src/pgraph/cullBinUnsorted.I +++ b/panda/src/pgraph/cullBinUnsorted.I @@ -17,21 +17,6 @@ //////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////// -// Function: CullBinUnsorted::GeomData::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE CullBinUnsorted::GeomData:: -GeomData(Geom *geom, const TransformState *transform, - const RenderState *state) : - _geom(geom), - _transform(transform), - _state(state) -{ -} - - //////////////////////////////////////////////////////////////////// // Function: CullBinUnsorted::Constructor // Access: Public diff --git a/panda/src/pgraph/cullBinUnsorted.cxx b/panda/src/pgraph/cullBinUnsorted.cxx index 19a721a162..923f052818 100644 --- a/panda/src/pgraph/cullBinUnsorted.cxx +++ b/panda/src/pgraph/cullBinUnsorted.cxx @@ -17,36 +17,49 @@ //////////////////////////////////////////////////////////////////// #include "cullBinUnsorted.h" +#include "cullHandler.h" #include "graphicsStateGuardianBase.h" TypeHandle CullBinUnsorted::_type_handle; //////////////////////////////////////////////////////////////////// -// Function: CullBinUnsorted::add_geom +// Function: CullBinUnsorted::Destructor // Access: Public, Virtual -// Description: Adds the geom, along with its associated state, to +// Description: +//////////////////////////////////////////////////////////////////// +CullBinUnsorted:: +~CullBinUnsorted() { + Objects::iterator oi; + for (oi = _objects.begin(); oi != _objects.end(); ++oi) { + CullableObject *object = (*oi); + delete object; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: CullBinUnsorted::add_object +// Access: Public, Virtual +// Description: Adds a geom, along with its associated state, to // the bin for rendering. //////////////////////////////////////////////////////////////////// void CullBinUnsorted:: -add_geom(Geom *geom, const TransformState *transform, - const RenderState *state) { - _geoms.push_back(GeomData(geom, transform, state)); +add_object(CullableObject *object) { + _objects.push_back(object); } //////////////////////////////////////////////////////////////////// // Function: CullBinUnsorted::draw // Access: Public -// Description: Draws all the geoms in the bin, in the appropriate +// Description: Draws all the objects in the bin, in the appropriate // order. //////////////////////////////////////////////////////////////////// void CullBinUnsorted:: draw() { - Geoms::iterator gi; - for (gi = _geoms.begin(); gi != _geoms.end(); ++gi) { - GeomData &geom_data = (*gi); - _gsg->set_state_and_transform(geom_data._state, geom_data._transform); - geom_data._geom->draw(_gsg); + Objects::iterator oi; + for (oi = _objects.begin(); oi != _objects.end(); ++oi) { + CullableObject *object = (*oi); + CullHandler::draw(object, _gsg); } } diff --git a/panda/src/pgraph/cullBinUnsorted.h b/panda/src/pgraph/cullBinUnsorted.h index eacaf0336e..b728682785 100644 --- a/panda/src/pgraph/cullBinUnsorted.h +++ b/panda/src/pgraph/cullBinUnsorted.h @@ -22,9 +22,6 @@ #include "pandabase.h" #include "cullBin.h" -#include "geom.h" -#include "transformState.h" -#include "renderState.h" #include "pointerTo.h" //////////////////////////////////////////////////////////////////// @@ -37,23 +34,14 @@ class EXPCL_PANDA CullBinUnsorted : public CullBin { public: INLINE CullBinUnsorted(GraphicsStateGuardianBase *gsg); + ~CullBinUnsorted(); - virtual void add_geom(Geom *geom, const TransformState *transform, - const RenderState *state); + virtual void add_object(CullableObject *object); virtual void draw(); private: - class GeomData { - public: - INLINE GeomData(Geom *geom, const TransformState *transform, - const RenderState *state); - PT(Geom) _geom; - CPT(TransformState) _transform; - CPT(RenderState) _state; - }; - - typedef pvector Geoms; - Geoms _geoms; + typedef pvector Objects; + Objects _objects; public: static TypeHandle get_class_type() { diff --git a/panda/src/pgraph/cullHandler.I b/panda/src/pgraph/cullHandler.I new file mode 100644 index 0000000000..9a80be99d6 --- /dev/null +++ b/panda/src/pgraph/cullHandler.I @@ -0,0 +1,35 @@ +// Filename: cullHandler.I +// Created by: drose (04Mar02) +// +//////////////////////////////////////////////////////////////////// +// +// 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: CullHandler::draw +// Access: Public, Static +// Description: Draws the indicated CullableObject, with full support +// for decals if they are attached to the object. The +// appropriate state is set on the GSG before drawing +// the object. +//////////////////////////////////////////////////////////////////// +INLINE void CullHandler:: +draw(CullableObject *object, GraphicsStateGuardianBase *gsg) { + if (object->_next != (CullableObject *)NULL) { + draw_with_decals(object, gsg); + } else { + gsg->set_state_and_transform(object->_state, object->_transform); + object->_geom->draw(gsg); + } +} diff --git a/panda/src/pgraph/cullHandler.cxx b/panda/src/pgraph/cullHandler.cxx index 103ef7d0f8..a7e7038097 100644 --- a/panda/src/pgraph/cullHandler.cxx +++ b/panda/src/pgraph/cullHandler.cxx @@ -17,6 +17,7 @@ //////////////////////////////////////////////////////////////////// #include "cullHandler.h" +#include "cullableObject.h" #include "geom.h" #include "transformState.h" #include "renderState.h" @@ -33,17 +34,66 @@ CullHandler:: //////////////////////////////////////////////////////////////////// -// Function: CullHandler::record_geom +// Function: CullHandler::record_object // Access: Public, Virtual // Description: This callback function is intended to be overridden // by a derived class. This is called as each Geom is // discovered by the CullTraverser. // -// This default method simply outputs a message to cerr; -// it's not intended to be used except for debugging. +// The CullHandler becomes the owner of the +// CullableObject pointer and is expected to delete it +// later. //////////////////////////////////////////////////////////////////// void CullHandler:: -record_geom(Geom *geom, const TransformState *transform, - const RenderState *state) { - cerr << *geom << " " << *transform << " " << *state << "\n"; +record_object(CullableObject *object) { + cerr << *object->_geom << " " << *object->_transform << " " << *object->_state << "\n"; + delete object; } + +//////////////////////////////////////////////////////////////////// +// Function: CullHandler::draw_with_decals +// Access: Public, Static +// Description: Draws the indicated CullableObject, assuming it has +// attached decals. +//////////////////////////////////////////////////////////////////// +void CullHandler:: +draw_with_decals(CullableObject *object, GraphicsStateGuardianBase *gsg) { + // We draw with a three-step process. + + // First, render all of the base geometry for the first pass. + CPT(RenderState) state = gsg->begin_decal_base_first(); + + CullableObject *base = object; + while (base != (CullableObject *)NULL && base->_geom != (Geom *)NULL) { + gsg->set_state_and_transform(base->_state->compose(state), base->_transform); + base->_geom->draw(gsg); + + base = base->_next; + } + + if (base != (CullableObject *)NULL) { + // Now, draw all the decals. + state = gsg->begin_decal_nested(); + + CullableObject *decal = base->_next; + while (decal != (CullableObject *)NULL) { + gsg->set_state_and_transform(decal->_state->compose(state), decal->_transform); + decal->_geom->draw(gsg); + + decal = decal->_next; + } + } + + // And now, re-draw the base geometry, if required. + state = gsg->begin_decal_base_second(); + if (state != (const RenderState *)NULL) { + base = object; + while (base != (CullableObject *)NULL && base->_geom != (Geom *)NULL) { + gsg->set_state_and_transform(base->_state->compose(state), base->_transform); + base->_geom->draw(gsg); + + base = base->_next; + } + } +} + diff --git a/panda/src/pgraph/cullHandler.h b/panda/src/pgraph/cullHandler.h index 4f122647f6..22c4af3c04 100644 --- a/panda/src/pgraph/cullHandler.h +++ b/panda/src/pgraph/cullHandler.h @@ -20,10 +20,8 @@ #define CULLHANDLER_H #include "pandabase.h" - -class Geom; -class TransformState; -class RenderState; +#include "cullableObject.h" +#include "graphicsStateGuardianBase.h" //////////////////////////////////////////////////////////////////// // Class : CullHandler @@ -36,13 +34,16 @@ class EXPCL_PANDA CullHandler { public: virtual ~CullHandler(); - // virtual void begin_decal(); - virtual void record_geom(Geom *geom, const TransformState *transform, - const RenderState *state); - // virtual void push_decal(); - // virtual void pop_decal(); + virtual void record_object(CullableObject *object); + + INLINE static void draw(CullableObject *object, + GraphicsStateGuardianBase *gsg); + static void draw_with_decals(CullableObject *object, + GraphicsStateGuardianBase *gsg); }; +#include "cullHandler.I" + #endif diff --git a/panda/src/pgraph/cullResult.I b/panda/src/pgraph/cullResult.I index 4d8692bea1..b44757d7ac 100644 --- a/panda/src/pgraph/cullResult.I +++ b/panda/src/pgraph/cullResult.I @@ -56,14 +56,16 @@ get_bin(int bin_index) { } //////////////////////////////////////////////////////////////////// -// Function: CullResult::add_geom +// Function: CullResult::add_object // Access: Public -// Description: Adds the indicated Geom to the appropriate bin. +// Description: Adds the indicated CullableObject to the appropriate +// bin. The bin becomes the owner of the object +// pointer, and will eventually delete it. //////////////////////////////////////////////////////////////////// INLINE void CullResult:: -add_geom(Geom *geom, const TransformState *transform, - const RenderState *state) { - CullBin *bin = get_bin(state->get_bin_index()); +add_object(CullableObject *object) { + nassertv(object->_state != (const RenderState *)NULL); + CullBin *bin = get_bin(object->_state->get_bin_index()); nassertv(bin != (CullBin *)NULL); - bin->add_geom(geom, transform, state); + bin->add_object(object); } diff --git a/panda/src/pgraph/cullResult.h b/panda/src/pgraph/cullResult.h index 3eddebb1b6..2e95e775cf 100644 --- a/panda/src/pgraph/cullResult.h +++ b/panda/src/pgraph/cullResult.h @@ -22,6 +22,7 @@ #include "pandabase.h" #include "cullBin.h" #include "renderState.h" +#include "cullableObject.h" #include "referenceCount.h" #include "pointerTo.h" @@ -52,8 +53,7 @@ public: INLINE CullBin *get_bin(int bin_index); - INLINE void add_geom(Geom *geom, const TransformState *transform, - const RenderState *state); + INLINE void add_object(CullableObject *object); void finish_cull(); void draw(); diff --git a/panda/src/pgraph/decalAttrib.I b/panda/src/pgraph/decalAttrib.I new file mode 100644 index 0000000000..83f1fccf9b --- /dev/null +++ b/panda/src/pgraph/decalAttrib.I @@ -0,0 +1,28 @@ +// Filename: decalAttrib.I +// Created by: drose (04Mar02) +// +//////////////////////////////////////////////////////////////////// +// +// 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: DecalAttrib::Constructor +// Access: Private +// Description: Use DecalAttrib::make() to construct a new +// DecalAttrib object. +//////////////////////////////////////////////////////////////////// +INLINE DecalAttrib:: +DecalAttrib() { +} diff --git a/panda/src/pgraph/decalAttrib.cxx b/panda/src/pgraph/decalAttrib.cxx new file mode 100644 index 0000000000..7b87d3aca2 --- /dev/null +++ b/panda/src/pgraph/decalAttrib.cxx @@ -0,0 +1,128 @@ +// Filename: decalAttrib.cxx +// Created by: drose (04Mar02) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "decalAttrib.h" +#include "bamReader.h" +#include "bamWriter.h" +#include "datagram.h" +#include "datagramIterator.h" + +TypeHandle DecalAttrib::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: DecalAttrib::make +// Access: Published, Static +// Description: Constructs a new DecalAttrib object. +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) DecalAttrib:: +make() { + DecalAttrib *attrib = new DecalAttrib; + return return_new(attrib); +} + +//////////////////////////////////////////////////////////////////// +// Function: DecalAttrib::compare_to_impl +// Access: Protected, Virtual +// Description: Intended to be overridden by derived DecalAttrib +// types to return a unique number indicating whether +// this DecalAttrib is equivalent to the other one. +// +// This should return 0 if the two DecalAttrib 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 DecalAttrib +// objects whose get_type() functions return the same. +//////////////////////////////////////////////////////////////////// +int DecalAttrib:: +compare_to_impl(const RenderAttrib *other) const { + // All DecalAttribs are equivalent--there are no properties to + // store. + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: DecalAttrib::make_default_impl +// Access: Protected, Virtual +// Description: Intended to be overridden by derived DecalAttrib +// types to specify what the default property for a +// DecalAttrib of this type should be. +// +// This should return a newly-allocated DecalAttrib of +// the same type that corresponds to whatever the +// standard default for this kind of DecalAttrib is. +//////////////////////////////////////////////////////////////////// +RenderAttrib *DecalAttrib:: +make_default_impl() const { + return new DecalAttrib; +} + +//////////////////////////////////////////////////////////////////// +// Function: DecalAttrib::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// DecalAttrib. +//////////////////////////////////////////////////////////////////// +void DecalAttrib:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: DecalAttrib::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void DecalAttrib:: +write_datagram(BamWriter *manager, Datagram &dg) { + RenderAttrib::write_datagram(manager, dg); +} + +//////////////////////////////////////////////////////////////////// +// Function: DecalAttrib::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type DecalAttrib is encountered +// in the Bam file. It should create the DecalAttrib +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *DecalAttrib:: +make_from_bam(const FactoryParams ¶ms) { + DecalAttrib *attrib = new DecalAttrib; + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + attrib->fillin(scan, manager); + + return attrib; +} + +//////////////////////////////////////////////////////////////////// +// Function: DecalAttrib::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 DecalAttrib. +//////////////////////////////////////////////////////////////////// +void DecalAttrib:: +fillin(DatagramIterator &scan, BamReader *manager) { + RenderAttrib::fillin(scan, manager); +} diff --git a/panda/src/pgraph/decalAttrib.h b/panda/src/pgraph/decalAttrib.h new file mode 100644 index 0000000000..8969e87e50 --- /dev/null +++ b/panda/src/pgraph/decalAttrib.h @@ -0,0 +1,72 @@ +// Filename: decalAttrib.h +// Created by: drose (04Mar02) +// +//////////////////////////////////////////////////////////////////// +// +// 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 DECALATTRIB_H +#define DECALATTRIB_H + +#include "pandabase.h" + +#include "renderAttrib.h" + +//////////////////////////////////////////////////////////////////// +// Class : DecalAttrib +// Description : Applied to a GeomNode to indicate that the children +// of this GeomNode are coplanar and should be drawn as +// decals (eliminating Z-fighting). +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA DecalAttrib : public RenderAttrib { +private: + INLINE DecalAttrib(); + +PUBLISHED: + static CPT(RenderAttrib) make(); + +protected: + virtual int compare_to_impl(const RenderAttrib *other) const; + virtual RenderAttrib *make_default_impl() const; + +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() { + RenderAttrib::init_type(); + register_type(_type_handle, "DecalAttrib", + 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 "decalAttrib.I" + +#endif + diff --git a/panda/src/pgraph/depthTestAttrib.I b/panda/src/pgraph/depthTestAttrib.I new file mode 100644 index 0000000000..6caf644e45 --- /dev/null +++ b/panda/src/pgraph/depthTestAttrib.I @@ -0,0 +1,40 @@ +// Filename: depthTestAttrib.I +// Created by: drose (04Mar02) +// +//////////////////////////////////////////////////////////////////// +// +// 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: DepthTestAttrib::Constructor +// Access: Private +// Description: Use DepthTestAttrib::make() to construct a new +// DepthTestAttrib object. +//////////////////////////////////////////////////////////////////// +INLINE DepthTestAttrib:: +DepthTestAttrib(DepthTestAttrib::Mode mode) : + _mode(mode) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: DepthTestAttrib::get_mode +// Access: Published +// Description: Returns the depth write mode. +//////////////////////////////////////////////////////////////////// +INLINE DepthTestAttrib::Mode DepthTestAttrib:: +get_mode() const { + return _mode; +} diff --git a/panda/src/pgraph/depthTestAttrib.cxx b/panda/src/pgraph/depthTestAttrib.cxx new file mode 100644 index 0000000000..488788a443 --- /dev/null +++ b/panda/src/pgraph/depthTestAttrib.cxx @@ -0,0 +1,199 @@ +// Filename: depthTestAttrib.cxx +// Created by: drose (04Mar02) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "depthTestAttrib.h" +#include "graphicsStateGuardianBase.h" +#include "dcast.h" +#include "bamReader.h" +#include "bamWriter.h" +#include "datagram.h" +#include "datagramIterator.h" + +TypeHandle DepthTestAttrib::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: DepthTestAttrib::make +// Access: Published, Static +// Description: Constructs a new DepthTestAttrib object that specifies +// how to cull geometry. By Panda convention, vertices +// are ordered counterclockwise when seen from the +// front, so the M_cull_clockwise will cull backfacing +// polygons. +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) DepthTestAttrib:: +make(DepthTestAttrib::Mode mode) { + DepthTestAttrib *attrib = new DepthTestAttrib(mode); + return return_new(attrib); +} + +//////////////////////////////////////////////////////////////////// +// Function: DepthTestAttrib::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 DepthTestAttrib:: +issue(GraphicsStateGuardianBase *gsg) const { + gsg->issue_depth_test(this); +} + +//////////////////////////////////////////////////////////////////// +// Function: DepthTestAttrib::output +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void DepthTestAttrib:: +output(ostream &out) const { + out << get_type() << ":"; + switch (get_mode()) { + case M_none: + out << "none"; + break; + + case M_never: + out << "never"; + break; + + case M_less: + out << "less"; + break; + + case M_equal: + out << "equal"; + break; + + case M_less_equal: + out << "less_equal"; + break; + + case M_greater: + out << "greater"; + break; + + case M_not_equal: + out << "not_equal"; + break; + + case M_greater_equal: + out << "greater_equal"; + break; + + case M_always: + out << "always"; + break; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: DepthTestAttrib::compare_to_impl +// Access: Protected, Virtual +// Description: Intended to be overridden by derived DepthTestAttrib +// types to return a unique number indicating whether +// this DepthTestAttrib is equivalent to the other one. +// +// This should return 0 if the two DepthTestAttrib 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 DepthTestAttrib +// objects whose get_type() functions return the same. +//////////////////////////////////////////////////////////////////// +int DepthTestAttrib:: +compare_to_impl(const RenderAttrib *other) const { + const DepthTestAttrib *ta; + DCAST_INTO_R(ta, other, 0); + return (int)_mode - (int)ta->_mode; +} + +//////////////////////////////////////////////////////////////////// +// Function: DepthTestAttrib::make_default_impl +// Access: Protected, Virtual +// Description: Intended to be overridden by derived DepthTestAttrib +// types to specify what the default property for a +// DepthTestAttrib of this type should be. +// +// This should return a newly-allocated DepthTestAttrib of +// the same type that corresponds to whatever the +// standard default for this kind of DepthTestAttrib is. +//////////////////////////////////////////////////////////////////// +RenderAttrib *DepthTestAttrib:: +make_default_impl() const { + return new DepthTestAttrib; +} + +//////////////////////////////////////////////////////////////////// +// Function: DepthTestAttrib::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// DepthTestAttrib. +//////////////////////////////////////////////////////////////////// +void DepthTestAttrib:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: DepthTestAttrib::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void DepthTestAttrib:: +write_datagram(BamWriter *manager, Datagram &dg) { + RenderAttrib::write_datagram(manager, dg); + + dg.add_int8(_mode); +} + +//////////////////////////////////////////////////////////////////// +// Function: DepthTestAttrib::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type DepthTestAttrib is encountered +// in the Bam file. It should create the DepthTestAttrib +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *DepthTestAttrib:: +make_from_bam(const FactoryParams ¶ms) { + DepthTestAttrib *attrib = new DepthTestAttrib; + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + attrib->fillin(scan, manager); + + return attrib; +} + +//////////////////////////////////////////////////////////////////// +// Function: DepthTestAttrib::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 DepthTestAttrib. +//////////////////////////////////////////////////////////////////// +void DepthTestAttrib:: +fillin(DatagramIterator &scan, BamReader *manager) { + RenderAttrib::fillin(scan, manager); + + _mode = (Mode)scan.get_int8(); +} diff --git a/panda/src/pgraph/depthTestAttrib.h b/panda/src/pgraph/depthTestAttrib.h new file mode 100644 index 0000000000..7fde73810e --- /dev/null +++ b/panda/src/pgraph/depthTestAttrib.h @@ -0,0 +1,92 @@ +// Filename: depthTestAttrib.h +// Created by: drose (04Mar02) +// +//////////////////////////////////////////////////////////////////// +// +// 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 DEPTHTESTATTRIB_H +#define DEPTHTESTATTRIB_H + +#include "pandabase.h" + +#include "renderAttrib.h" + +//////////////////////////////////////////////////////////////////// +// Class : DepthTestAttrib +// Description : Enables or disables writing to the depth buffer. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA DepthTestAttrib : public RenderAttrib { +PUBLISHED: + enum Mode { + M_none, // No depth test; may still write to depth buffer. + M_never, // Never draw. + M_less, // incoming < stored + M_equal, // incoming == stored + M_less_equal, // incoming <= stored + M_greater, // incoming > stored + M_not_equal, // incoming != stored + M_greater_equal, // incoming >= stored + M_always // Always draw. Same effect as none, more expensive. + }; + +private: + INLINE DepthTestAttrib(Mode mode = M_less); + +PUBLISHED: + static CPT(RenderAttrib) make(Mode mode); + + INLINE Mode get_mode() 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 RenderAttrib *make_default_impl() const; + +private: + Mode _mode; + +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() { + RenderAttrib::init_type(); + register_type(_type_handle, "DepthTestAttrib", + 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 "depthTestAttrib.I" + +#endif + diff --git a/panda/src/pgraph/depthWriteAttrib.I b/panda/src/pgraph/depthWriteAttrib.I new file mode 100644 index 0000000000..ea0fe50297 --- /dev/null +++ b/panda/src/pgraph/depthWriteAttrib.I @@ -0,0 +1,40 @@ +// Filename: depthWriteAttrib.I +// Created by: drose (04Mar02) +// +//////////////////////////////////////////////////////////////////// +// +// 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: DepthWriteAttrib::Constructor +// Access: Private +// Description: Use DepthWriteAttrib::make() to construct a new +// DepthWriteAttrib object. +//////////////////////////////////////////////////////////////////// +INLINE DepthWriteAttrib:: +DepthWriteAttrib(DepthWriteAttrib::Mode mode) : + _mode(mode) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: DepthWriteAttrib::get_mode +// Access: Published +// Description: Returns the depth write mode. +//////////////////////////////////////////////////////////////////// +INLINE DepthWriteAttrib::Mode DepthWriteAttrib:: +get_mode() const { + return _mode; +} diff --git a/panda/src/pgraph/depthWriteAttrib.cxx b/panda/src/pgraph/depthWriteAttrib.cxx new file mode 100644 index 0000000000..7779add63d --- /dev/null +++ b/panda/src/pgraph/depthWriteAttrib.cxx @@ -0,0 +1,170 @@ +// Filename: depthWriteAttrib.cxx +// Created by: drose (04Mar02) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "depthWriteAttrib.h" +#include "graphicsStateGuardianBase.h" +#include "dcast.h" +#include "bamReader.h" +#include "bamWriter.h" +#include "datagram.h" +#include "datagramIterator.h" + +TypeHandle DepthWriteAttrib::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: DepthWriteAttrib::make +// Access: Published, Static +// Description: Constructs a new DepthWriteAttrib object that specifies +// how to cull geometry. By Panda convention, vertices +// are ordered counterclockwise when seen from the +// front, so the M_cull_clockwise will cull backfacing +// polygons. +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) DepthWriteAttrib:: +make(DepthWriteAttrib::Mode mode) { + DepthWriteAttrib *attrib = new DepthWriteAttrib(mode); + return return_new(attrib); +} + +//////////////////////////////////////////////////////////////////// +// Function: DepthWriteAttrib::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 DepthWriteAttrib:: +issue(GraphicsStateGuardianBase *gsg) const { + gsg->issue_depth_write(this); +} + +//////////////////////////////////////////////////////////////////// +// Function: DepthWriteAttrib::output +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void DepthWriteAttrib:: +output(ostream &out) const { + out << get_type() << ":"; + switch (get_mode()) { + case M_off: + out << "off"; + break; + case M_on: + out << "on"; + break; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: DepthWriteAttrib::compare_to_impl +// Access: Protected, Virtual +// Description: Intended to be overridden by derived DepthWriteAttrib +// types to return a unique number indicating whether +// this DepthWriteAttrib is equivalent to the other one. +// +// This should return 0 if the two DepthWriteAttrib 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 DepthWriteAttrib +// objects whose get_type() functions return the same. +//////////////////////////////////////////////////////////////////// +int DepthWriteAttrib:: +compare_to_impl(const RenderAttrib *other) const { + const DepthWriteAttrib *ta; + DCAST_INTO_R(ta, other, 0); + return (int)_mode - (int)ta->_mode; +} + +//////////////////////////////////////////////////////////////////// +// Function: DepthWriteAttrib::make_default_impl +// Access: Protected, Virtual +// Description: Intended to be overridden by derived DepthWriteAttrib +// types to specify what the default property for a +// DepthWriteAttrib of this type should be. +// +// This should return a newly-allocated DepthWriteAttrib of +// the same type that corresponds to whatever the +// standard default for this kind of DepthWriteAttrib is. +//////////////////////////////////////////////////////////////////// +RenderAttrib *DepthWriteAttrib:: +make_default_impl() const { + return new DepthWriteAttrib; +} + +//////////////////////////////////////////////////////////////////// +// Function: DepthWriteAttrib::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// DepthWriteAttrib. +//////////////////////////////////////////////////////////////////// +void DepthWriteAttrib:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: DepthWriteAttrib::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void DepthWriteAttrib:: +write_datagram(BamWriter *manager, Datagram &dg) { + RenderAttrib::write_datagram(manager, dg); + + dg.add_int8(_mode); +} + +//////////////////////////////////////////////////////////////////// +// Function: DepthWriteAttrib::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type DepthWriteAttrib is encountered +// in the Bam file. It should create the DepthWriteAttrib +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *DepthWriteAttrib:: +make_from_bam(const FactoryParams ¶ms) { + DepthWriteAttrib *attrib = new DepthWriteAttrib; + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + attrib->fillin(scan, manager); + + return attrib; +} + +//////////////////////////////////////////////////////////////////// +// Function: DepthWriteAttrib::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 DepthWriteAttrib. +//////////////////////////////////////////////////////////////////// +void DepthWriteAttrib:: +fillin(DatagramIterator &scan, BamReader *manager) { + RenderAttrib::fillin(scan, manager); + + _mode = (Mode)scan.get_int8(); +} diff --git a/panda/src/pgraph/depthWriteAttrib.h b/panda/src/pgraph/depthWriteAttrib.h new file mode 100644 index 0000000000..c206396a63 --- /dev/null +++ b/panda/src/pgraph/depthWriteAttrib.h @@ -0,0 +1,85 @@ +// Filename: depthWriteAttrib.h +// Created by: drose (04Mar02) +// +//////////////////////////////////////////////////////////////////// +// +// 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 DEPTHWRITEATTRIB_H +#define DEPTHWRITEATTRIB_H + +#include "pandabase.h" + +#include "renderAttrib.h" + +//////////////////////////////////////////////////////////////////// +// Class : DepthWriteAttrib +// Description : Enables or disables writing to the depth buffer. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA DepthWriteAttrib : public RenderAttrib { +PUBLISHED: + enum Mode { + M_off, + M_on + }; + +private: + INLINE DepthWriteAttrib(Mode mode = M_on); + +PUBLISHED: + static CPT(RenderAttrib) make(Mode mode); + + INLINE Mode get_mode() 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 RenderAttrib *make_default_impl() const; + +private: + Mode _mode; + +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() { + RenderAttrib::init_type(); + register_type(_type_handle, "DepthWriteAttrib", + 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 "depthWriteAttrib.I" + +#endif + diff --git a/panda/src/display/drawCullHandler.I b/panda/src/pgraph/drawCullHandler.I similarity index 94% rename from panda/src/display/drawCullHandler.I rename to panda/src/pgraph/drawCullHandler.I index 3b968f9c50..b43e237316 100644 --- a/panda/src/display/drawCullHandler.I +++ b/panda/src/pgraph/drawCullHandler.I @@ -23,7 +23,7 @@ // Description: //////////////////////////////////////////////////////////////////// INLINE DrawCullHandler:: -DrawCullHandler(GraphicsStateGuardian *gsg) : +DrawCullHandler(GraphicsStateGuardianBase *gsg) : _gsg(gsg) { } diff --git a/panda/src/display/drawCullHandler.cxx b/panda/src/pgraph/drawCullHandler.cxx similarity index 81% rename from panda/src/display/drawCullHandler.cxx rename to panda/src/pgraph/drawCullHandler.cxx index 99f7bcc17f..ba9c14f4d1 100644 --- a/panda/src/display/drawCullHandler.cxx +++ b/panda/src/pgraph/drawCullHandler.cxx @@ -17,23 +17,22 @@ //////////////////////////////////////////////////////////////////// #include "drawCullHandler.h" +#include "cullableObject.h" #include "geom.h" #include "transformState.h" #include "renderState.h" -#include "graphicsStateGuardian.h" +#include "graphicsStateGuardianBase.h" //////////////////////////////////////////////////////////////////// -// Function: DrawCullHandler::record_geom +// Function: DrawCullHandler::record_object // Access: Public, Virtual // Description: This callback function is intended to be overridden // by a derived class. This is called as each Geom is // discovered by the CullTraverser. //////////////////////////////////////////////////////////////////// void DrawCullHandler:: -record_geom(Geom *geom, const TransformState *transform, - const RenderState *state) { - _gsg->set_transform(transform); - _gsg->set_state(state); - geom->draw(_gsg); +record_object(CullableObject *object) { + draw(object, _gsg); + delete object; } diff --git a/panda/src/display/drawCullHandler.h b/panda/src/pgraph/drawCullHandler.h similarity index 82% rename from panda/src/display/drawCullHandler.h rename to panda/src/pgraph/drawCullHandler.h index 6ebccef3eb..f8fce0ab89 100644 --- a/panda/src/display/drawCullHandler.h +++ b/panda/src/pgraph/drawCullHandler.h @@ -22,7 +22,7 @@ #include "pandabase.h" #include "cullHandler.h" -class GraphicsStateGuardian; +class GraphicsStateGuardianBase; //////////////////////////////////////////////////////////////////// // Class : DrawCullHandler @@ -37,16 +37,12 @@ class GraphicsStateGuardian; //////////////////////////////////////////////////////////////////// class EXPCL_PANDA DrawCullHandler : public CullHandler { public: - INLINE DrawCullHandler(GraphicsStateGuardian *gsg); + INLINE DrawCullHandler(GraphicsStateGuardianBase *gsg); - // virtual void begin_decal(); - virtual void record_geom(Geom *geom, const TransformState *transform, - const RenderState *state); - // virtual void push_decal(); - // virtual void pop_decal(); + virtual void record_object(CullableObject *object); private: - GraphicsStateGuardian *_gsg; + GraphicsStateGuardianBase *_gsg; }; #include "drawCullHandler.I" diff --git a/panda/src/pgraph/nodeChain.I b/panda/src/pgraph/nodeChain.I index d48b871664..54e95077f8 100644 --- a/panda/src/pgraph/nodeChain.I +++ b/panda/src/pgraph/nodeChain.I @@ -163,6 +163,31 @@ node() const { return _head->get_node(); } +//////////////////////////////////////////////////////////////////// +// Function: NodeChain::get_num_children +// Access: Published +// Description: Returns the number of children of the bottom node. +//////////////////////////////////////////////////////////////////// +INLINE int NodeChain:: +get_num_children() const { + nassertr(!is_empty(), 0); + return _head->get_node()->get_num_children(); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodeChain::get_child +// Access: Published +// Description: Returns a NodeChain representing the nth child of the +// bottom node. +//////////////////////////////////////////////////////////////////// +INLINE NodeChain NodeChain:: +get_child(int n) const { + nassertr(n >= 0 && n < get_num_children(), NodeChain()); + NodeChain child; + child._head = PandaNode::get_component(_head, _head->get_node()->get_child(n)); + return child; +} + //////////////////////////////////////////////////////////////////// // Function: NodeChain::has_parent // Access: Published @@ -184,8 +209,8 @@ has_parent() const { INLINE NodeChain NodeChain:: get_parent() const { nassertr(has_parent(), NodeChain::fail()); - NodeChain parent(*this); - parent._head = parent._head->get_next(); + NodeChain parent; + parent._head = _head->get_next(); return parent; } diff --git a/panda/src/pgraph/nodeChain.h b/panda/src/pgraph/nodeChain.h index 170ecad89e..0ef9512287 100644 --- a/panda/src/pgraph/nodeChain.h +++ b/panda/src/pgraph/nodeChain.h @@ -91,9 +91,9 @@ PUBLISHED: /* NodeChainCollection get_siblings() const; NodeChainCollection get_children() const; + */ INLINE int get_num_children() const; INLINE NodeChain get_child(int n) const; - */ INLINE bool has_parent() const; INLINE NodeChain get_parent() const; diff --git a/panda/src/pgraph/pgraph_composite1.cxx b/panda/src/pgraph/pgraph_composite1.cxx index 64bd3734f9..4f08f644ac 100644 --- a/panda/src/pgraph/pgraph_composite1.cxx +++ b/panda/src/pgraph/pgraph_composite1.cxx @@ -2,6 +2,7 @@ #include "binCullHandler.cxx" #include "qpcamera.cxx" #include "colorAttrib.cxx" +#include "colorWriteAttrib.cxx" #include "config_pgraph.cxx" #include "cullBin.cxx" #include "cullBinAttrib.cxx" diff --git a/panda/src/pgraph/pgraph_composite2.cxx b/panda/src/pgraph/pgraph_composite2.cxx index 4e1a634895..d9a7bdf166 100644 --- a/panda/src/pgraph/pgraph_composite2.cxx +++ b/panda/src/pgraph/pgraph_composite2.cxx @@ -1,3 +1,8 @@ +#include "cullableObject.cxx" +#include "decalAttrib.cxx" +#include "depthTestAttrib.cxx" +#include "depthWriteAttrib.cxx" +#include "drawCullHandler.cxx" #include "qpgeomNode.cxx" #include "qplensNode.cxx" #include "nodeChain.cxx" diff --git a/panda/src/pgraph/qpcullTraverser.cxx b/panda/src/pgraph/qpcullTraverser.cxx index 195daaaa78..51a3a8b493 100644 --- a/panda/src/pgraph/qpcullTraverser.cxx +++ b/panda/src/pgraph/qpcullTraverser.cxx @@ -167,10 +167,7 @@ r_traverse(PandaNode *node, // actually culling an object we simply force it to be drawn in // red wireframe. view_frustum = (GeometricBoundingVolume *)NULL; - CPT(RenderState) fake_effect = RenderState::make - (ColorAttrib::make_flat(Colorf(1.0f, 0.0f, 0.0f, 1.0f)), - TextureAttrib::make_off(), - 1000); + CPT(RenderState) fake_effect = get_fake_view_frustum_cull_effect(); next_state = next_state->compose(fake_effect); } else if ((result & BoundingVolume::IF_all) != 0) { @@ -196,16 +193,16 @@ r_traverse(PandaNode *node, PT(GeometricBoundingVolume) next_view_frustum = view_frustum; PT(GeometricBoundingVolume) next_guard_band = guard_band; - const TransformState *transform = node->get_transform(); - if (!transform->is_identity()) { - next_render_transform = render_transform->compose(transform); - next_net_transform = net_transform->compose(transform); + const TransformState *node_transform = node->get_transform(); + if (!node_transform->is_identity()) { + next_render_transform = render_transform->compose(node_transform); + next_net_transform = net_transform->compose(node_transform); if ((view_frustum != (GeometricBoundingVolume *)NULL) || (guard_band != (GeometricBoundingVolume *)NULL)) { // We need to move the viewing frustums into the node's // coordinate space by applying the node's inverse transform. - if (transform->is_singular()) { + if (node_transform->is_singular()) { // But we can't invert a singular transform! Instead of // trying, we'll just give up on frustum culling from this // point down. @@ -214,7 +211,7 @@ r_traverse(PandaNode *node, } else { CPT(TransformState) inv_transform = - transform->invert_compose(TransformState::make_identity()); + node_transform->invert_compose(TransformState::make_identity()); if (view_frustum != (GeometricBoundingVolume *)NULL) { next_view_frustum = DCAST(GeometricBoundingVolume, view_frustum->make_copy()); @@ -229,9 +226,10 @@ r_traverse(PandaNode *node, } } - next_state = next_state->compose(node->get_state()); + const RenderState *node_state = node->get_state(); + next_state = next_state->compose(node_state); - const BillboardAttrib *billboard = state->get_billboard(); + const BillboardAttrib *billboard = node_state->get_billboard(); if (billboard != (const BillboardAttrib *)NULL) { // Got to apply a billboard transform here. CPT(TransformState) billboard_transform = @@ -245,24 +243,162 @@ r_traverse(PandaNode *node, next_view_frustum = (GeometricBoundingVolume *)NULL; } + if (node_state->has_decal()) { + start_decal(node, next_render_transform, next_state); + + } else { + if (node->is_geom_node()) { + qpGeomNode *geom_node = DCAST(qpGeomNode, node); + + // Get all the Geoms, with no decalling. + int num_geoms = geom_node->get_num_geoms(); + for (int i = 0; i < num_geoms; i++) { + CullableObject *object = new CullableObject; + object->_geom = geom_node->get_geom(i); + object->_state = next_state->compose(geom_node->get_geom_state(i)); + object->_transform = next_render_transform; + _cull_handler->record_object(object); + } + } + + // Now visit all the node's children. + PandaNode::Children cr = node->get_children(); + int num_children = cr.get_num_children(); + for (int i = 0; i < num_children; i++) { + r_traverse(cr.get_child(i), next_render_transform, next_net_transform, + next_state, next_view_frustum, next_guard_band); + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpCullTraverser::start_decal +// Access: Private +// Description: Collects a base node and all of the decals applied to +// it. This involves recursing below the base GeomNode +// to find all the decal geoms; we don't bother to apply +// any view-frustum culling at this point, and we don't +// presently support billboards or LOD's within the +// decals. Hard to justify the duplicate code this +// would require. +//////////////////////////////////////////////////////////////////// +void qpCullTraverser:: +start_decal(PandaNode *node, + const TransformState *render_transform, + const RenderState *state) { + if (!node->is_geom_node()) { + pgraph_cat.error() + << "DecalAttrib applied to " << *node << ", not a GeomNode.\n"; + return; + } + + // Build a chain of CullableObjects. The head of the chain will be + // all of the base Geoms in order, followed by an empty + // CullableObject node, followed by all of the decal Geoms, in + // order. + + const TransformState *next_render_transform = render_transform; + const RenderState *next_state = state; + + // Since the CullableObject is a linked list which gets built in + // LIFO order, we start with the decals. + CullableObject *decals = (CullableObject *)NULL; + PandaNode::Children cr = node->get_children(); + int num_children = cr.get_num_children(); + for (int i = num_children - 1; i >= 0; i--) { + decals = + r_get_decals(cr.get_child(i), next_render_transform, next_state, decals); + } + + // Now create a new, empty CullableObject to separate the decals + // from the non-decals. + CullableObject *separator = new CullableObject(decals); + + // And now get the base Geoms, again in reverse order. + CullableObject *object = separator; + qpGeomNode *geom_node = DCAST(qpGeomNode, node); + + // Get all the Geoms, with no decalling. + int num_geoms = geom_node->get_num_geoms(); + for (int i = num_geoms - 1; i >= 0; i--) { + object = new CullableObject(object); + object->_geom = geom_node->get_geom(i); + object->_state = next_state->compose(geom_node->get_geom_state(i)); + object->_transform = next_render_transform; + } + + if (object != separator) { + // Finally, send the whole list down to the CullHandler for + // processing. The first Geom in the node now represents the + // overall state. + _cull_handler->record_object(object); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpCullTraverser::r_get_decals +// Access: Private +// Description: Recursively gets all the decals applied to a +// particular GeomNode. These are built into a +// CullableObject list in LIFO order (so that the +// traversing the list will extract them in the order +// they were encountered in the scene graph). +//////////////////////////////////////////////////////////////////// +CullableObject *qpCullTraverser:: +r_get_decals(PandaNode *node, + const TransformState *render_transform, + const RenderState *state, + CullableObject *decals) { + const TransformState *node_transform = node->get_transform(); + const RenderState *node_state = node->get_state(); + + CPT(TransformState) next_render_transform = + render_transform->compose(node_transform); + CPT(RenderState) next_state = + state->compose(node_state); + + // First, visit all of the node's children. + PandaNode::Children cr = node->get_children(); + int num_children = cr.get_num_children(); + for (int i = num_children - 1; i >= 0; i--) { + decals = + r_get_decals(cr.get_child(i), next_render_transform, next_state, decals); + } + + // Now, tack on any geoms within the node. if (node->is_geom_node()) { - qpGeomNode *geom_node; - DCAST_INTO_V(geom_node, node); - + qpGeomNode *geom_node = DCAST(qpGeomNode, node); + int num_geoms = geom_node->get_num_geoms(); - for (int i = 0; i < num_geoms; i++) { - Geom *geom = geom_node->get_geom(i); - CPT(RenderState) geom_state = - next_state->compose(geom_node->get_geom_state(i)); - _cull_handler->record_geom(geom, next_render_transform, geom_state); + for (int i = num_geoms - 1; i >= 0; i--) { + decals = new CullableObject(decals); + decals->_geom = geom_node->get_geom(i); + decals->_state = next_state->compose(geom_node->get_geom_state(i)); + decals->_transform = next_render_transform; } } - // Now visit all the node's children. - PandaNode::Children cr = node->get_children(); - int num_children = cr.get_num_children(); - for (int i = 0; i < num_children; i++) { - r_traverse(cr.get_child(i), next_render_transform, next_net_transform, - next_state, next_view_frustum, next_guard_band); - } + return decals; } + +//////////////////////////////////////////////////////////////////// +// Function: qpCullTraverser::get_fake_view_frustum_cull_effect +// Access: Private, Static +// Description: Returns a RenderState for rendering stuff in red +// wireframe, strictly for the fake_view_frustum_cull +// effect. +//////////////////////////////////////////////////////////////////// +CPT(RenderState) qpCullTraverser:: +get_fake_view_frustum_cull_effect() { + // Once someone asks for this pointer, we hold its reference count + // and never free it. + static CPT(RenderState) effect = (const RenderState *)NULL; + if (effect == (const RenderState *)NULL) { + effect = RenderState::make + (ColorAttrib::make_flat(Colorf(1.0f, 0.0f, 0.0f, 1.0f)), + TextureAttrib::make_off(), + 1000); + } + return effect; +} + diff --git a/panda/src/pgraph/qpcullTraverser.h b/panda/src/pgraph/qpcullTraverser.h index 8b7c494748..99e149aff3 100644 --- a/panda/src/pgraph/qpcullTraverser.h +++ b/panda/src/pgraph/qpcullTraverser.h @@ -56,6 +56,15 @@ private: const RenderState *state, GeometricBoundingVolume *view_frustum, GeometricBoundingVolume *guard_band); + void start_decal(PandaNode *node, + const TransformState *render_transform, + const RenderState *state); + CullableObject *r_get_decals(PandaNode *node, + const TransformState *render_transform, + const RenderState *state, + CullableObject *decals); + + static CPT(RenderState) get_fake_view_frustum_cull_effect(); CPT(RenderState) _initial_state; CPT(TransformState) _camera_transform; diff --git a/panda/src/pgraph/renderState.I b/panda/src/pgraph/renderState.I index 1aaf50186d..80fae74760 100644 --- a/panda/src/pgraph/renderState.I +++ b/panda/src/pgraph/renderState.I @@ -181,6 +181,27 @@ get_billboard() const { return _billboard; } +//////////////////////////////////////////////////////////////////// +// Function: RenderState::has_decal +// Access: Public +// Description: This function is provided as an optimization, to +// speed up the render-time checking for the existance +// of a DecalAttrib on this state. It returns true if a +// DecalAttrib exists, false otherwise. Note that since +// there is no additional information stored on the +// DecalAttrib, there's no point in returning it if it +// exists. +//////////////////////////////////////////////////////////////////// +INLINE bool RenderState:: +has_decal() const { + if ((_flags & F_checked_decal) == 0) { + // We pretend this function is const, even though it transparently + // modifies the internal decal cache. + ((RenderState *)this)->determine_decal(); + } + return ((_flags & F_has_decal) != 0); +} + //////////////////////////////////////////////////////////////////// // Function: RenderState::get_bin_index // Access: Public diff --git a/panda/src/pgraph/renderState.cxx b/panda/src/pgraph/renderState.cxx index a76ba406e5..ab8e096fb3 100644 --- a/panda/src/pgraph/renderState.cxx +++ b/panda/src/pgraph/renderState.cxx @@ -540,9 +540,9 @@ write(ostream &out, int indent_level) const { CPT(RenderState) RenderState:: issue_delta_modify(const RenderState *other, GraphicsStateGuardianBase *gsg) const { - if (other == this) { - // If the state doesn't change, that's a trivial special case. - return other; + if (other->is_empty()) { + // If the other state is empty, that's a trivial special case. + return this; } // First, build a new Attributes member that represents the union of @@ -622,9 +622,9 @@ issue_delta_modify(const RenderState *other, CPT(RenderState) RenderState:: issue_delta_set(const RenderState *other, GraphicsStateGuardianBase *gsg) const { - if (other->is_empty()) { - // If the other state is empty, that's a trivial special case. - return this; + if (other == this) { + // If the state doesn't change, that's a trivial special case. + return other; } // We don't need to build a new RenderState, because the return @@ -860,6 +860,20 @@ determine_billboard() { _flags |= F_checked_billboard; } +//////////////////////////////////////////////////////////////////// +// Function: RenderState::determine_decal +// Access: Private +// Description: This is the private implementation of has_decal(). +//////////////////////////////////////////////////////////////////// +void RenderState:: +determine_decal() { + const RenderAttrib *attrib = get_attrib(DecalAttrib::get_class_type()); + if (attrib != (const RenderAttrib *)NULL) { + _flags |= F_has_decal; + } + _flags |= F_checked_decal; +} + //////////////////////////////////////////////////////////////////// // Function: RenderState::determine_bin_index // Access: Private diff --git a/panda/src/pgraph/renderState.h b/panda/src/pgraph/renderState.h index 334f285527..f82feb0b24 100644 --- a/panda/src/pgraph/renderState.h +++ b/panda/src/pgraph/renderState.h @@ -88,6 +88,7 @@ PUBLISHED: public: INLINE const BillboardAttrib *get_billboard() const; + INLINE bool has_decal() const; INLINE int get_bin_index() const; INLINE int get_draw_order() const; @@ -103,6 +104,7 @@ private: CPT(RenderState) do_compose(const RenderState *other) const; CPT(RenderState) do_invert_compose(const RenderState *other) const; void determine_billboard(); + void determine_decal(); void determine_bin_index(); private: @@ -157,8 +159,8 @@ private: typedef ov_set Attributes; Attributes _attributes; - // We cache the pointer to the BillboardAttrib stored in the state, - // if there is one. + // We cache the pointer to the some critical attributes stored in + // the state, if they exist. const BillboardAttrib *_billboard; // We also cache the index to the associated GeomBin. @@ -168,6 +170,8 @@ private: enum Flags { F_checked_billboard = 0x0001, F_checked_bin_index = 0x0002, + F_checked_decal = 0x0004, + F_has_decal = 0x0008, }; short _flags;