From faa13d10e559383c9ae1f7550175860b4c082430 Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 9 Jan 2001 03:07:29 +0000 Subject: [PATCH] *** empty log message *** --- direct/src/showbase/showBase.cxx | 37 ++- direct/src/showbase/showBase.h | 11 +- panda/src/collide/collisionRay.I | 2 +- panda/src/collide/collisionRay.cxx | 4 +- panda/src/collide/collisionRay.h | 4 +- panda/src/cull/config_cull.cxx | 4 + panda/src/cull/config_cull.h | 2 + panda/src/cull/cullLevelState.h | 3 + panda/src/cull/cullState.I | 13 +- panda/src/cull/cullState.cxx | 18 +- panda/src/cull/cullState.h | 14 +- panda/src/cull/cullStateLookup.cxx | 33 +++ panda/src/cull/cullStateSubtree.cxx | 9 +- panda/src/cull/cullTraverser.I | 60 ++++- panda/src/cull/cullTraverser.cxx | 92 ++++++-- panda/src/cull/cullTraverser.h | 18 +- panda/src/cull/geomBinBackToFront.I | 15 +- panda/src/cull/geomBinBackToFront.cxx | 15 +- panda/src/cull/geomBinBackToFront.h | 4 +- panda/src/cull/geomBinFixed.I | 15 +- panda/src/cull/geomBinFixed.cxx | 12 +- panda/src/cull/geomBinFixed.h | 4 +- panda/src/cull/geomBinUnsorted.cxx | 20 +- panda/src/display/graphicsStateGuardian.I | 2 +- panda/src/display/graphicsStateGuardian.h | 8 +- panda/src/dxgsg/dxGraphicsStateGuardian.cxx | 6 +- panda/src/dxgsg/dxGraphicsStateGuardian.h | 4 +- panda/src/effects/lensFlareNode.cxx | 10 +- panda/src/effects/lensFlareNode.h | 5 +- panda/src/express/pointerTo.I | 14 +- panda/src/express/referenceCount.I | 12 +- panda/src/express/referenceCount.cxx | 32 --- panda/src/express/referenceCount.h | 7 +- panda/src/glgsg/glGraphicsStateGuardian.cxx | 6 +- panda/src/glgsg/glGraphicsStateGuardian.h | 4 +- panda/src/graph/Sources.pp | 16 +- panda/src/graph/arcChain.I | 219 ++++++++++++++++++ panda/src/graph/arcChain.cxx | 79 +++++++ panda/src/graph/arcChain.h | 105 +++++++++ panda/src/graph/config_graph.cxx | 9 +- panda/src/graph/config_graph.h | 1 + panda/src/graph/matrixTransition.I | 13 +- panda/src/graph/node.cxx | 2 +- panda/src/graph/node.h | 4 +- panda/src/graph/nodeRelation.I | 14 ++ panda/src/graph/nodeRelation.cxx | 12 +- panda/src/graph/nodeRelation.h | 10 +- panda/src/graph/nodeTransition.cxx | 2 +- panda/src/graph/nodeTransition.h | 4 +- panda/src/graph/wrt.I | 208 ++++++++++++++--- panda/src/graph/wrt.h | 22 +- panda/src/gui/guiManager.cxx | 57 +++-- panda/src/gui/guiManager.h | 3 +- panda/src/light/spotlight.cxx | 2 +- panda/src/putil/updateSeq.I | 61 ++++- panda/src/putil/updateSeq.h | 12 +- panda/src/ribgsg/ribGraphicsStateGuardian.cxx | 6 +- panda/src/ribgsg/ribGraphicsStateGuardian.h | 4 +- panda/src/sgattrib/billboardTransition.cxx | 8 +- panda/src/sgattrib/billboardTransition.h | 2 +- panda/src/sgattrib/drawBoundsTransition.cxx | 5 +- panda/src/sgattrib/drawBoundsTransition.h | 2 +- panda/src/sgattrib/pruneTransition.cxx | 2 +- panda/src/sgattrib/pruneTransition.h | 2 +- panda/src/sgraph/projectionNode.cxx | 43 ++-- panda/src/sgraph/projectionNode.h | 10 +- panda/src/sgraph/renderTraverser.I | 97 +++++++- panda/src/sgraph/renderTraverser.h | 23 +- .../src/sgraphutil/directRenderTraverser.cxx | 36 ++- panda/src/sgraphutil/directRenderTraverser.h | 3 +- panda/src/sgraphutil/frustumCullTraverser.I | 13 +- panda/src/sgraphutil/frustumCullTraverser.h | 6 +- panda/src/shader/shaderTransition.cxx | 4 +- panda/src/shader/shaderTransition.h | 2 +- panda/src/switchnode/LODNode.cxx | 12 +- panda/src/switchnode/LODNode.h | 2 +- panda/src/switchnode/sequenceNode.cxx | 9 +- panda/src/switchnode/sequenceNode.h | 2 +- panda/src/testbed/Sources.pp | 1 + panda/src/testbed/chat_test.cxx | 8 +- panda/src/testbed/demo.cxx | 19 +- 81 files changed, 1322 insertions(+), 373 deletions(-) create mode 100644 panda/src/graph/arcChain.I create mode 100644 panda/src/graph/arcChain.cxx create mode 100644 panda/src/graph/arcChain.h diff --git a/direct/src/showbase/showBase.cxx b/direct/src/showbase/showBase.cxx index 22ed16609d..3d49b89a9c 100644 --- a/direct/src/showbase/showBase.cxx +++ b/direct/src/showbase/showBase.cxx @@ -66,6 +66,7 @@ public: _data_root(data_root), _initial_state(initial_state), _app_traverser(RenderRelation::get_class_type()) { } + virtual ~WindowCallback() { } virtual void draw(bool) { _app_traverser.traverse(_render); @@ -156,7 +157,7 @@ PT(GraphicsWindow) make_graphics_window(GraphicsPipe *pipe, // can contain 2-d geometry and will be rendered on top of the // existing 3-d window. Returns the top node of the scene graph. NodePath -setup_panda_2d(PT(GraphicsWindow) win) { +setup_panda_2d(GraphicsWindow *win) { PT(Node) render2d_top; render2d_top = new NamedNode("render2d_top"); @@ -165,6 +166,12 @@ setup_panda_2d(PT(GraphicsWindow) win) { // Set up some overrides to turn off certain properties which we // probably won't need for 2-d objects. + + // It's particularly important to turn off the depth test, since + // we'll be keeping the same depth buffer already filled by the + // previously-drawn 3-d scene--we don't want to pay for a clear + // operation, but we also don't want to collide with that depth + // buffer. render2d_arc->set_transition(new DepthTestTransition(DepthTestProperty::M_none), 1); render2d_arc->set_transition(new DepthWriteTransition(DepthWriteTransition::off()), 1); render2d_arc->set_transition(new LightTransition(LightTransition::all_off()), 1); @@ -174,26 +181,32 @@ setup_panda_2d(PT(GraphicsWindow) win) { // Create a 2-d camera. Camera *cam2d = new Camera("cam2d"); new RenderRelation(render2d, cam2d); - cam2d->set_scene(render2d_top); Frustumf frustum2d; frustum2d.make_ortho(-1000,1000); cam2d->set_projection(OrthoProjection(frustum2d)); - // Now create a new layer. - GraphicsChannel *chan = win->get_channel(0); - nassertr(chan != (GraphicsChannel *)NULL, NodePath()); - - GraphicsLayer *layer = chan->make_layer(); - nassertr(layer != (GraphicsLayer *)NULL, NodePath()); - - DisplayRegion *dr = layer->make_display_region(); - nassertr(dr != (DisplayRegion *)NULL, NodePath()); - dr->set_camera(cam2d); + add_render_layer(win, render2d_top, cam2d); return NodePath(render2d_arc); } +// Create an auxiliary scene graph starting at the indicated node, +// layered on top of the previously-created layers. +void +add_render_layer(GraphicsWindow *win, Node *render_top, Camera *camera) { + GraphicsChannel *chan = win->get_channel(0); + nassertv(chan != (GraphicsChannel *)NULL); + + GraphicsLayer *layer = chan->make_layer(); + nassertv(layer != (GraphicsLayer *)NULL); + + DisplayRegion *dr = layer->make_display_region(); + nassertv(dr != (DisplayRegion *)NULL); + camera->set_scene(render_top); + dr->set_camera(camera); +} + // Enable the collision traversal using a particular traverser. void set_collision_traverser(CollisionTraverser *traverser) { collision_traverser = traverser; diff --git a/direct/src/showbase/showBase.h b/direct/src/showbase/showBase.h index e0041ba9c8..a06b046074 100644 --- a/direct/src/showbase/showBase.h +++ b/direct/src/showbase/showBase.h @@ -17,16 +17,11 @@ #include #include -#define testint 1 -#define testfloat 1.2345 -#define testcstring "testcstring" -#include -#define teststring string("teststring") - ConfigureDecl(config_showbase, EXPCL_DIRECT, EXPTP_DIRECT); typedef Config::Config ConfigShowbase; class CollisionTraverser; +class Camera; BEGIN_PUBLISH @@ -39,7 +34,9 @@ EXPCL_DIRECT PT(GraphicsWindow) NodeAttributes &initial_state ); -EXPCL_DIRECT NodePath setup_panda_2d(PT(GraphicsWindow) win); +EXPCL_DIRECT NodePath setup_panda_2d(GraphicsWindow *win); +EXPCL_DIRECT void add_render_layer(GraphicsWindow *win, Node *render_top, + Camera *camera); EXPCL_DIRECT void set_collision_traverser(CollisionTraverser *traverser); EXPCL_DIRECT CollisionTraverser *get_collision_traverser(); diff --git a/panda/src/collide/collisionRay.I b/panda/src/collide/collisionRay.I index d8d2b024b9..ce92a038aa 100644 --- a/panda/src/collide/collisionRay.I +++ b/panda/src/collide/collisionRay.I @@ -128,6 +128,6 @@ get_direction() const { // the screen given a camera and a mouse location. //////////////////////////////////////////////////////////////////// INLINE bool CollisionRay:: -set_projection(const ProjectionNode *camera, float px, float py) { +set_projection(ProjectionNode *camera, float px, float py) { return set_projection(camera, LPoint2f(px, py)); } diff --git a/panda/src/collide/collisionRay.cxx b/panda/src/collide/collisionRay.cxx index 9697bf02ed..59cb76b0ac 100644 --- a/panda/src/collide/collisionRay.cxx +++ b/panda/src/collide/collisionRay.cxx @@ -75,8 +75,8 @@ output(ostream &out) const { // otherwise. //////////////////////////////////////////////////////////////////// bool CollisionRay:: -set_projection(const ProjectionNode *camera, const LPoint2f &point) { - const Projection *proj = camera->get_projection(); +set_projection(ProjectionNode *camera, const LPoint2f &point) { + Projection *proj = camera->get_projection(); bool success = true; if (!proj->extrude(point, _origin, _direction)) { diff --git a/panda/src/collide/collisionRay.h b/panda/src/collide/collisionRay.h index 32c0a3cfdc..b61ebde429 100644 --- a/panda/src/collide/collisionRay.h +++ b/panda/src/collide/collisionRay.h @@ -49,8 +49,8 @@ PUBLISHED: INLINE void set_direction(float x, float y, float z); INLINE const LVector3f &get_direction() const; - bool set_projection(const ProjectionNode *camera, const LPoint2f &point); - INLINE bool set_projection(const ProjectionNode *camera, float px, float py); + bool set_projection(ProjectionNode *camera, const LPoint2f &point); + INLINE bool set_projection(ProjectionNode *camera, float px, float py); protected: virtual void recompute_bound(); diff --git a/panda/src/cull/config_cull.cxx b/panda/src/cull/config_cull.cxx index 6f60a701aa..15cc4ccc2b 100644 --- a/panda/src/cull/config_cull.cxx +++ b/panda/src/cull/config_cull.cxx @@ -33,3 +33,7 @@ ConfigureFn(config_cull) { DirectRenderTransition::init_type(); } +// Set this true to force all of the caching to blow itself away every +// frame. Normally you would only do this during testing. +const bool cull_force_update = config_cull.GetBool("cull-force-update", false); + diff --git a/panda/src/cull/config_cull.h b/panda/src/cull/config_cull.h index 78091d2e6e..2602f702c2 100644 --- a/panda/src/cull/config_cull.h +++ b/panda/src/cull/config_cull.h @@ -11,4 +11,6 @@ NotifyCategoryDecl(cull, EXPCL_PANDA, EXPTP_PANDA); +extern const bool cull_force_update; + #endif diff --git a/panda/src/cull/cullLevelState.h b/panda/src/cull/cullLevelState.h index 2b85da916f..a1804e0f11 100644 --- a/panda/src/cull/cullLevelState.h +++ b/panda/src/cull/cullLevelState.h @@ -10,6 +10,8 @@ #include "cullStateLookup.h" +#include + //////////////////////////////////////////////////////////////////// // Class : CullLevelState // Description : This is the state information the @@ -19,6 +21,7 @@ class EXPCL_PANDA CullLevelState { public: CullStateLookup *_lookup; + UpdateSeq _now; }; #endif diff --git a/panda/src/cull/cullState.I b/panda/src/cull/cullState.I index b6cb479a67..690379a8e7 100644 --- a/panda/src/cull/cullState.I +++ b/panda/src/cull/cullState.I @@ -79,8 +79,13 @@ clear_current_nodes() { // be visible this frame. //////////////////////////////////////////////////////////////////// INLINE void CullState:: -record_current_geom_node(const PT(GeomNode) &node) { - _current_geom_nodes.push_back(node); +record_current_geom_node(const ArcChain &arc_chain) { + if (cull_cat.is_spam()) { + cull_cat.spam() + << "Recording geom node " << arc_chain << " with state " << (void *)this + << "\n"; + } + _current_geom_nodes.push_back(arc_chain); _empty_frames_count = 0; } @@ -92,8 +97,8 @@ record_current_geom_node(const PT(GeomNode) &node) { // visible this frame. //////////////////////////////////////////////////////////////////// INLINE void CullState:: -record_current_direct_node(const PT_Node &node) { - _current_direct_nodes.push_back(node); +record_current_direct_node(const ArcChain &arc_chain) { + _current_direct_nodes.push_back(arc_chain); _empty_frames_count = 0; } diff --git a/panda/src/cull/cullState.cxx b/panda/src/cull/cullState.cxx index f986344b1e..55a21d29c0 100644 --- a/panda/src/cull/cullState.cxx +++ b/panda/src/cull/cullState.cxx @@ -4,6 +4,7 @@ //////////////////////////////////////////////////////////////////// #include "cullState.h" +#include "config_cull.h" #include #include @@ -26,7 +27,14 @@ check_currency(Node *node, const AllTransitionsWrapper &, nassertr(vi != _verified.end(), false); UpdateSeq verified_stamp = (*vi).second; - if (verified_stamp == now) { + + if (cull_cat.is_spam()) { + cull_cat.spam() + << "Checking currency for " << *node << ", verified_stamp = " + << verified_stamp << " now = " << now << "\n"; + } + + if (verified_stamp == now && !verified_stamp.is_fresh()) { return true; } @@ -63,10 +71,10 @@ write(ostream &out, int indent_level) const { if (!_current_geom_nodes.empty()) { CurrentGeomNodes::const_iterator ci; ci = _current_geom_nodes.begin(); - out << " (" << *(*ci); + out << " (" << (*ci); ++ci; while (ci != _current_geom_nodes.end()) { - out << ", " << *(*ci); + out << ", " << (*ci); ++ci; } out << ")"; @@ -77,10 +85,10 @@ write(ostream &out, int indent_level) const { if (!_current_direct_nodes.empty()) { CurrentDirectNodes::const_iterator ci; ci = _current_direct_nodes.begin(); - out << " (" << *(*ci); + out << " (" << (*ci); ++ci; while (ci != _current_direct_nodes.end()) { - out << ", " << *(*ci); + out << ", " << (*ci); ++ci; } out << ")"; diff --git a/panda/src/cull/cullState.h b/panda/src/cull/cullState.h index 33ee73769d..6343308530 100644 --- a/panda/src/cull/cullState.h +++ b/panda/src/cull/cullState.h @@ -8,6 +8,8 @@ #include +#include "config_cull.h" + #include #include #include @@ -15,10 +17,10 @@ #include #include #include -#include -#include +#include #include +#include class GraphicsStateGuardian; class GeomBin; @@ -34,8 +36,8 @@ class GeomBin; //////////////////////////////////////////////////////////////////// class EXPCL_PANDA CullState : public ReferenceCount { public: - typedef vector CurrentGeomNodes; - typedef vector_PT_Node CurrentDirectNodes; + typedef vector CurrentGeomNodes; + typedef vector CurrentDirectNodes; public: INLINE CullState(const AllTransitionsWrapper &trans); @@ -50,8 +52,8 @@ public: INLINE void mark_verified(Node *node, UpdateSeq now); INLINE void clear_current_nodes(); - INLINE void record_current_geom_node(const PT(GeomNode) &node); - INLINE void record_current_direct_node(const PT_Node &node); + INLINE void record_current_geom_node(const ArcChain &arc_chain); + INLINE void record_current_direct_node(const ArcChain &arc_chain); INLINE bool is_empty() const; INLINE int count_current_nodes() const; INLINE int get_empty_frames_count() const; diff --git a/panda/src/cull/cullStateLookup.cxx b/panda/src/cull/cullStateLookup.cxx index 0fa0352383..04808bf215 100644 --- a/panda/src/cull/cullStateLookup.cxx +++ b/panda/src/cull/cullStateLookup.cxx @@ -50,20 +50,36 @@ CullState *CullStateLookup:: find_node(Node *node, const AllTransitionsWrapper &trans, UpdateSeq now) { + if (cull_cat.is_spam()) { + cull_cat.spam() + << "Looking up " << *node << " in lookup " << (void *)this << "\n"; + } CullStates::iterator csi; csi = _cull_states.find(node); if (csi == _cull_states.end()) { // No entry for the node. + if (cull_cat.is_spam()) { + cull_cat.spam() + << "No entry for the node.\n"; + } return NULL; } CullState *cs = (*csi).second; if (cs->check_currency(node, trans, now)) { // The entry is current enough to use. + if (cull_cat.is_spam()) { + cull_cat.spam() + << "The entry is found and current.\n"; + } return cs; } // The entry is stale; remove it and return NULL. + if (cull_cat.is_spam()) { + cull_cat.spam() + << "The entry is stale.\n"; + } _cull_states.erase(csi); return NULL; } @@ -94,10 +110,19 @@ get_subtree(const PT(NodeRelation) &arc, const AllTransitionsWrapper &trans, Node *top_subtree, UpdateSeq now) { + if (cull_cat.is_spam()) { + cull_cat.spam() + << "Getting subtree for " << *arc << " in lookup " + << (void *)this << "\n"; + } Subtrees::iterator si; si = _subtrees.find(arc); if (si == _subtrees.end()) { // No entry for the arc. + if (cull_cat.is_spam()) { + cull_cat.spam() + << "No entry for the arc; creating new one.\n"; + } CullStateSubtree *subtree = new CullStateSubtree(this, trans, top_subtree, now); _subtrees.insert(Subtrees::value_type(arc, subtree)); @@ -107,10 +132,18 @@ get_subtree(const PT(NodeRelation) &arc, CullStateSubtree *subtree = (*si).second; if (subtree->check_currency(trans, top_subtree, now)) { // The entry is current enough to use. + if (cull_cat.is_spam()) { + cull_cat.spam() + << "The entry is found and current.\n"; + } return subtree; } // The entry is stale; update it. + if (cull_cat.is_spam()) { + cull_cat.spam() + << "The entry is stale.\n"; + } subtree->update(trans, top_subtree, now); return subtree; } diff --git a/panda/src/cull/cullStateSubtree.cxx b/panda/src/cull/cullStateSubtree.cxx index 3b84abbae6..46d70d4738 100644 --- a/panda/src/cull/cullStateSubtree.cxx +++ b/panda/src/cull/cullStateSubtree.cxx @@ -4,6 +4,7 @@ //////////////////////////////////////////////////////////////////// #include "cullStateSubtree.h" +#include "config_cull.h" //////////////////////////////////////////////////////////////////// @@ -25,13 +26,19 @@ CullStateSubtree:: bool CullStateSubtree:: check_currency(const AllTransitionsWrapper &, Node *top_subtree, UpdateSeq now) { + if (cull_cat.is_spam()) { + cull_cat.spam() + << "Checking currency for subtree " << (void *)this + << ", _verified = " << _verified << " now = " << now << "\n"; + } + // Make sure we've still got the same top_subtree node. if (_top_subtree != top_subtree) { return false; } // First, check the verified time stamp. - if (_verified == now) { + if (_verified == now && !_verified.is_fresh()) { return true; } diff --git a/panda/src/cull/cullTraverser.I b/panda/src/cull/cullTraverser.I index 58d5695649..eec82da8df 100644 --- a/panda/src/cull/cullTraverser.I +++ b/panda/src/cull/cullTraverser.I @@ -56,6 +56,22 @@ draw_geom(GeomNode *geom_node, const AllAttributesWrapper &initial_state) { geom_node->draw(_gsg); } +//////////////////////////////////////////////////////////////////// +// Function: CullTraverser::draw_geom +// Access: Public +// Description: Sets up the GSG to draw the indicated GeomNode in the +// indicated state. If the state so demands it and the +// GeomNode has children, draws the rest of the +// hierarchy below it immediately. +//////////////////////////////////////////////////////////////////// +INLINE void CullTraverser:: +draw_geom(const ArcChain &arc_chain, const AllAttributesWrapper &initial_state) { + nassertv(!arc_chain.empty()); + GeomNode *geom_node; + DCAST_INTO_V(geom_node, arc_chain.back()->get_child()); + draw_geom(geom_node, initial_state); +} + //////////////////////////////////////////////////////////////////// // Function: CullTraverser::draw_direct // Access: Public @@ -63,13 +79,16 @@ draw_geom(GeomNode *geom_node, const AllAttributesWrapper &initial_state) { // indicated node, and including all nested nodes below. //////////////////////////////////////////////////////////////////// INLINE void CullTraverser:: -draw_direct(Node *node, const AllAttributesWrapper &initial_state) { +draw_direct(const ArcChain &arc_chain, + const AllAttributesWrapper &initial_state) { + nassertv(!arc_chain.empty()); + Node *node = arc_chain.back()->get_child(); if (cull_cat.is_spam()) { cull_cat.spam() << "Drawing " << *node << " in direct mode.\n"; } nassertv(node != (Node *)NULL); - DirectRenderTraverser drt(_gsg, _graph_type); + DirectRenderTraverser drt(_gsg, _graph_type, arc_chain); drt.traverse(node, initial_state, AllTransitionsWrapper()); } @@ -87,14 +106,15 @@ draw_direct(Node *node, const AllAttributesWrapper &initial_state) { INLINE CullStateLookup *CullTraverser:: add_instance(NodeRelation *arc, const AllTransitionsWrapper &trans, Node *top_subtree, const CullLevelState &level_state) { - return level_state._lookup->get_subtree(arc, trans, top_subtree, _now); + return level_state._lookup->get_subtree + (arc, trans, top_subtree, level_state._now); } //////////////////////////////////////////////////////////////////// // Function: CullTraverser::find_bin_state // Access: Private // Description: Looks for a CullState in the set that corresponds to -// the indicates set of transitions; if one is found, +// the indicated set of transitions; if one is found, // returns its pointer; otherwise, creates a new one and // returns it. //////////////////////////////////////////////////////////////////// @@ -108,14 +128,32 @@ find_bin_state(const AllTransitionsWrapper &trans) { // corresponding CullState that is (now) stored in the set. pair result = _states.insert(cs); - /* - if (result.second) { - // The insert succeeded, so the CullState was not there - // previously. - cerr << "Created CullState for:\n"; - trans.write(cerr, 2); + if (cull_cat.is_spam()) { + if (result.second) { + // The insert succeeded, so the CullState was not there + // previously. + cull_cat.spam() + << "Created CullState " << (void *)cs << " for:\n"; + trans.write(cull_cat.spam(false), 2); + } else { + cull_cat.spam() + << "Found existing CullState " << (void *)(*result.first) + << " for:\n"; + trans.write(cull_cat.spam(false), 2); + } } - */ return *result.first; } + +//////////////////////////////////////////////////////////////////// +// Function: CullTraverser::backward_arc +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void CullTraverser:: +backward_arc(NodeRelation *arc, NullTransitionWrapper &, + NullAttributeWrapper &, NullAttributeWrapper &, + const CullLevelState &) { + mark_backward_arc(arc); +} diff --git a/panda/src/cull/cullTraverser.cxx b/panda/src/cull/cullTraverser.cxx index ab44644ecb..686fd16fc4 100644 --- a/panda/src/cull/cullTraverser.cxx +++ b/panda/src/cull/cullTraverser.cxx @@ -14,9 +14,10 @@ #include #include #include -#include #include #include +#include +#include #include #include // for implicit_app_traversal #include @@ -36,8 +37,9 @@ PStatCollector CullTraverser::_draw_pcollector = // Description: //////////////////////////////////////////////////////////////////// CullTraverser:: -CullTraverser(GraphicsStateGuardian *gsg, TypeHandle graph_type) : - RenderTraverser(gsg, graph_type) +CullTraverser(GraphicsStateGuardian *gsg, TypeHandle graph_type, + const ArcChain &arc_chain) : + RenderTraverser(gsg, graph_type, arc_chain) { _default_bin = new GeomBinNormal("default", this); _nested_count = 0; @@ -85,9 +87,14 @@ traverse(Node *root, nassertv(!_bins.empty()); - _now = last_graph_update[_graph_type]; - bool is_initial = (_nested_count == 0); + if (is_initial) { + if (cull_force_update) { + _now = UpdateSeq::fresh(); + } else { + _now = UpdateSeq::initial(); + } + } _nested_count++; if (is_initial) { @@ -101,8 +108,25 @@ traverse(Node *root, CullLevelState level_state; level_state._lookup = &_lookup; - fc_traverse(root, *this, NullAttributeWrapper(), level_state, - _gsg, _graph_type); + level_state._now = _now; + + // Determine the relative transform matrix from the camera to our + // starting node. This is important for proper view-frustum + // culling. + LMatrix4f rel_from_camera; + NodeTransitionWrapper ntw(TransformTransition::get_class_type()); + wrt(_gsg->get_current_projection_node(), root, begin(), end(), + ntw, get_graph_type()); + const TransformTransition *tt; + if (get_transition_into(tt, ntw)) { + rel_from_camera = tt->get_matrix(); + } else { + // No relative transform. + rel_from_camera = LMatrix4f::ident_mat(); + } + + fc_traverse(root, rel_from_camera, *this, NullAttributeWrapper(), + level_state, _gsg, _graph_type); if (is_initial) { draw(); @@ -262,9 +286,12 @@ clean_out_old_states() { // appropriate bin. //////////////////////////////////////////////////////////////////// void CullTraverser:: -add_geom_node(const PT(GeomNode) &node, const AllTransitionsWrapper &trans, +add_geom_node(GeomNode *node, const AllTransitionsWrapper &trans, const CullLevelState &level_state) { nassertv(node != (GeomNode *)NULL); + const ArcChain &arc_chain = get_arc_chain(); + nassertv(!arc_chain.empty()); + nassertv(arc_chain.back()->get_child() == node); AllTransitionsWrapper complete_trans; level_state._lookup->compose_trans(trans, complete_trans); @@ -275,17 +302,23 @@ add_geom_node(const PT(GeomNode) &node, const AllTransitionsWrapper &trans, // remove it here just to be paranoid. complete_trans.clear_transition(DirectRenderTransition::get_class_type()); - CullState *cs = level_state._lookup->find_node(node, complete_trans, _now); + CullState *cs = level_state._lookup->find_node + (node, complete_trans, level_state._now); if (cs == (CullState *)NULL) { + if (cull_cat.is_spam()) { + cull_cat.spam() + << "Finding a new bin state\n"; + } + // The node didn't have a previously-associated CullState that we // could use, so determine a new one for it. cs = find_bin_state(complete_trans); nassertv(cs != (CullState *)NULL); - level_state._lookup->record_node(node, cs, _now); + level_state._lookup->record_node(node, cs, level_state._now); } - cs->record_current_geom_node(node); + cs->record_current_geom_node(arc_chain); } //////////////////////////////////////////////////////////////////// @@ -294,13 +327,16 @@ add_geom_node(const PT(GeomNode) &node, const AllTransitionsWrapper &trans, // Description: Records the indicated Node as one that is immediately // under a DirectRenderTransition, and thus it and its // subtree should be rendered directly, in a depth-first -// traversal. This is usuall done when the render order +// traversal. This is usually done when the render order // is very important within a small subtree of nodes. //////////////////////////////////////////////////////////////////// void CullTraverser:: -add_direct_node(const PT_Node &node, const AllTransitionsWrapper &trans, +add_direct_node(Node *node, const AllTransitionsWrapper &trans, const CullLevelState &level_state) { nassertv(node != (Node *)NULL); + const ArcChain &arc_chain = get_arc_chain(); + nassertv(!arc_chain.empty()); + nassertv(arc_chain.back()->get_child() == node); AllTransitionsWrapper complete_trans; level_state._lookup->compose_trans(trans, complete_trans); @@ -309,17 +345,18 @@ add_direct_node(const PT_Node &node, const AllTransitionsWrapper &trans, // and interfere with state-sorting. complete_trans.clear_transition(DirectRenderTransition::get_class_type()); - CullState *cs = level_state._lookup->find_node(node, complete_trans, _now); + CullState *cs = level_state._lookup->find_node + (node, complete_trans, level_state._now); if (cs == (CullState *)NULL) { // The node didn't have a previously-associated CullState that we // could use, so determine a new one for it. cs = find_bin_state(complete_trans); nassertv(cs != (CullState *)NULL); - level_state._lookup->record_node(node, cs, _now); + level_state._lookup->record_node(node, cs, level_state._now); } - cs->record_current_direct_node(node); + cs->record_current_direct_node(arc_chain); } //////////////////////////////////////////////////////////////////// @@ -346,6 +383,11 @@ forward_arc(NodeRelation *arc, NullTransitionWrapper &, AllTransitionsWrapper trans; + UpdateSeq last_update = arc->get_last_update(); + if (level_state._now < last_update) { + level_state._now = last_update; + } + bool is_instanced = (node->get_num_parents(_graph_type) > 1); bool is_geom = node->is_of_type(GeomNode::get_class_type()); bool node_has_sub_render = node->has_sub_render(); @@ -354,10 +396,18 @@ forward_arc(NodeRelation *arc, NullTransitionWrapper &, arc->has_transition(DirectRenderTransition::get_class_type()) || arc->has_transition(DecalTransition::get_class_type()); + if (arc_has_sub_render) { + level_state._now = UpdateSeq::fresh(); + } + _now = level_state._now; + + mark_forward_arc(arc); + if (cull_cat.is_spam()) { cull_cat.spam() << "Reached " << *node << ":\n" - << "is_instanced = " << is_instanced + << " now = " << level_state._now + << " is_instanced = " << is_instanced << " is_geom = " << is_geom << " node_has_sub_render = " << node_has_sub_render << " arc_has_sub_render = " << arc_has_sub_render @@ -382,10 +432,9 @@ forward_arc(NodeRelation *arc, NullTransitionWrapper &, AllTransitionsWrapper new_trans; - if (!arc->sub_render_trans(attrib, new_trans, _gsg)) { - return false; - } - if (!node->sub_render(attrib, new_trans, _gsg)) { + if (!arc->sub_render_trans(attrib, new_trans, this) || + !node->sub_render(attrib, new_trans, this)) { + mark_backward_arc(arc); return false; } @@ -399,6 +448,7 @@ forward_arc(NodeRelation *arc, NullTransitionWrapper &, // traverse any further beyond it--the rest of the subgraph // beginning at this node will be traversed when the node is // rendered. + mark_backward_arc(arc); return false; } diff --git a/panda/src/cull/cullTraverser.h b/panda/src/cull/cullTraverser.h index 8e9ca397c2..c3fdf5ca5c 100644 --- a/panda/src/cull/cullTraverser.h +++ b/panda/src/cull/cullTraverser.h @@ -37,7 +37,8 @@ class EXPCL_PANDA CullTraverser : public RenderTraverser, public TraverserVisitor { public: - CullTraverser(GraphicsStateGuardian *gsg, TypeHandle graph_type); + CullTraverser(GraphicsStateGuardian *gsg, TypeHandle graph_type, + const ArcChain &arc_chain = ArcChain()); virtual ~CullTraverser(); INLINE void set_default_bin(GeomBin *bin); @@ -49,7 +50,9 @@ public: INLINE void draw_geom(GeomNode *geom_node, const AllAttributesWrapper &initial_state); - INLINE void draw_direct(Node *node, + INLINE void draw_geom(const ArcChain &arc_chain, + const AllAttributesWrapper &initial_state); + INLINE void draw_direct(const ArcChain &arc_chain, const AllAttributesWrapper &initial_state); PUBLISHED: @@ -60,10 +63,10 @@ private: void draw(); void clean_out_old_states(); - void add_geom_node(const PT(GeomNode) &node, + void add_geom_node(GeomNode *node, const AllTransitionsWrapper &trans, const CullLevelState &level_state); - void add_direct_node(const PT_Node &node, + void add_direct_node(Node *node, const AllTransitionsWrapper &trans, const CullLevelState &level_state); @@ -83,8 +86,12 @@ public: NullAttributeWrapper &pre, NullAttributeWrapper &post, CullLevelState &level_state); + INLINE void + backward_arc(NodeRelation *arc, NullTransitionWrapper &trans, + NullAttributeWrapper &pre, NullAttributeWrapper &post, + const CullLevelState &level_state); + private: - UpdateSeq _now; AllAttributesWrapper _initial_state; typedef set Bins; @@ -96,6 +103,7 @@ private: CullStateLookup _lookup; int _nested_count; + UpdateSeq _now; public: // Statistics diff --git a/panda/src/cull/geomBinBackToFront.I b/panda/src/cull/geomBinBackToFront.I index e558425efd..caf280a710 100644 --- a/panda/src/cull/geomBinBackToFront.I +++ b/panda/src/cull/geomBinBackToFront.I @@ -12,10 +12,10 @@ //////////////////////////////////////////////////////////////////// INLINE GeomBinBackToFront::NodeEntry:: NodeEntry(float distance, const PT(CullState) &state, - Node *node, bool is_direct) : + const ArcChain &arc_chain, bool is_direct) : _distance(distance), _state(state), - _node(node), + _arc_chain(arc_chain), _is_direct(is_direct) { } @@ -29,7 +29,7 @@ INLINE GeomBinBackToFront::NodeEntry:: NodeEntry(const GeomBinBackToFront::NodeEntry ©) : _distance(copy._distance), _state(copy._state), - _node(copy._node), + _arc_chain(copy._arc_chain), _is_direct(copy._is_direct) { } @@ -43,7 +43,7 @@ INLINE void GeomBinBackToFront::NodeEntry:: operator = (const NodeEntry ©) { _distance = copy._distance; _state = copy._state; - _node = copy._node; + _arc_chain = copy._arc_chain; } //////////////////////////////////////////////////////////////////// @@ -63,12 +63,11 @@ operator < (const NodeEntry &other) const { //////////////////////////////////////////////////////////////////// INLINE void GeomBinBackToFront::NodeEntry:: draw(CullTraverser *trav) const { - nassertv(_node != (GeomNode *)NULL); + nassertv(!_arc_chain.empty()); if (_is_direct) { - trav->draw_direct(_node, AllAttributesWrapper(_state->get_attributes())); + trav->draw_direct(_arc_chain, AllAttributesWrapper(_state->get_attributes())); } else { - trav->draw_geom(DCAST(GeomNode, _node), - AllAttributesWrapper(_state->get_attributes())); + trav->draw_geom(_arc_chain, AllAttributesWrapper(_state->get_attributes())); } } diff --git a/panda/src/cull/geomBinBackToFront.cxx b/panda/src/cull/geomBinBackToFront.cxx index 6aea6679be..1a558ab9f7 100644 --- a/panda/src/cull/geomBinBackToFront.cxx +++ b/panda/src/cull/geomBinBackToFront.cxx @@ -31,7 +31,7 @@ clear_current_states() { //////////////////////////////////////////////////////////////////// // Function: GeomBinBackToFront::record_current_state // Access: Public, Virtual -// Description: Called each frame by the CullTraverser to indicated +// Description: Called each frame by the CullTraverser to indicate // that the given CullState (and all of its current // GeomNodes) is visible this frame. //////////////////////////////////////////////////////////////////// @@ -45,7 +45,10 @@ record_current_state(GraphicsStateGuardian *gsg, CullState *cs, int, CullState::geom_const_iterator gi; for (gi = cs->geom_begin(); gi != cs->geom_end(); ++gi) { - GeomNode *node = (*gi); + const ArcChain &arc_chain = (*gi); + nassertv(!arc_chain.empty()); + GeomNode *node; + DCAST_INTO_V(node, arc_chain.back()->get_child()); nassertv(node != (GeomNode *)NULL); const BoundingVolume &volume = node->get_bound(); @@ -60,13 +63,15 @@ record_current_state(GraphicsStateGuardian *gsg, CullState *cs, int, } float distance = gsg->compute_distance_to(center); - _node_entries.insert(NodeEntry(distance, cs, node, false)); + _node_entries.insert(NodeEntry(distance, cs, arc_chain, false)); } } CullState::direct_const_iterator di; for (di = cs->direct_begin(); di != cs->direct_end(); ++di) { - Node *node = (*di); + const ArcChain &arc_chain = (*di); + nassertv(!arc_chain.empty()); + Node *node = arc_chain.back()->get_child(); nassertv(node != (Node *)NULL); const BoundingVolume &volume = node->get_bound(); @@ -119,7 +124,7 @@ record_current_state(GraphicsStateGuardian *gsg, CullState *cs, int, } } - _node_entries.insert(NodeEntry(distance, cs, node, true)); + _node_entries.insert(NodeEntry(distance, cs, arc_chain, true)); } } diff --git a/panda/src/cull/geomBinBackToFront.h b/panda/src/cull/geomBinBackToFront.h index 23a10cde04..3957a50c09 100644 --- a/panda/src/cull/geomBinBackToFront.h +++ b/panda/src/cull/geomBinBackToFront.h @@ -40,7 +40,7 @@ private: class NodeEntry { public: INLINE NodeEntry(float distance, const PT(CullState) &state, - Node *node, bool is_direct); + const ArcChain &arc_chain, bool is_direct); INLINE NodeEntry(const NodeEntry ©); INLINE void operator = (const NodeEntry ©); @@ -51,7 +51,7 @@ private: private: float _distance; PT(CullState) _state; - Node *_node; + ArcChain _arc_chain; bool _is_direct; }; diff --git a/panda/src/cull/geomBinFixed.I b/panda/src/cull/geomBinFixed.I index 9aa047f7c5..760a715b9c 100644 --- a/panda/src/cull/geomBinFixed.I +++ b/panda/src/cull/geomBinFixed.I @@ -12,10 +12,10 @@ //////////////////////////////////////////////////////////////////// INLINE GeomBinFixed::NodeEntry:: NodeEntry(int draw_order, const PT(CullState) &state, - Node *node, bool is_direct) : + const ArcChain &arc_chain, bool is_direct) : _draw_order(draw_order), _state(state), - _node(node), + _arc_chain(arc_chain), _is_direct(is_direct) { } @@ -29,7 +29,7 @@ INLINE GeomBinFixed::NodeEntry:: NodeEntry(const GeomBinFixed::NodeEntry ©) : _draw_order(copy._draw_order), _state(copy._state), - _node(copy._node), + _arc_chain(copy._arc_chain), _is_direct(copy._is_direct) { } @@ -43,7 +43,7 @@ INLINE void GeomBinFixed::NodeEntry:: operator = (const NodeEntry ©) { _draw_order = copy._draw_order; _state = copy._state; - _node = copy._node; + _arc_chain = copy._arc_chain; _is_direct = copy._is_direct; } @@ -64,12 +64,11 @@ operator < (const NodeEntry &other) const { //////////////////////////////////////////////////////////////////// INLINE void GeomBinFixed::NodeEntry:: draw(CullTraverser *trav) const { - nassertv(_node != (GeomNode *)NULL); + nassertv(!_arc_chain.empty()); if (_is_direct) { - trav->draw_direct(_node, AllAttributesWrapper(_state->get_attributes())); + trav->draw_direct(_arc_chain, AllAttributesWrapper(_state->get_attributes())); } else { - trav->draw_geom(DCAST(GeomNode, _node), - AllAttributesWrapper(_state->get_attributes())); + trav->draw_geom(_arc_chain, AllAttributesWrapper(_state->get_attributes())); } } diff --git a/panda/src/cull/geomBinFixed.cxx b/panda/src/cull/geomBinFixed.cxx index 7f598b8161..cc1cba0670 100644 --- a/panda/src/cull/geomBinFixed.cxx +++ b/panda/src/cull/geomBinFixed.cxx @@ -32,7 +32,7 @@ clear_current_states() { //////////////////////////////////////////////////////////////////// // Function: GeomBinFixed::record_current_state // Access: Public, Virtual -// Description: Called each frame by the CullTraverser to indicated +// Description: Called each frame by the CullTraverser to indicate // that the given CullState (and all of its current // GeomNodes) is visible this frame. //////////////////////////////////////////////////////////////////// @@ -46,16 +46,14 @@ record_current_state(GraphicsStateGuardian *, CullState *cs, CullState::geom_const_iterator gi; for (gi = cs->geom_begin(); gi != cs->geom_end(); ++gi) { - GeomNode *node = (*gi); - nassertv(node != (GeomNode *)NULL); - _node_entries.insert(NodeEntry(draw_order, cs, node, false)); + const ArcChain &arc_chain = (*gi); + _node_entries.insert(NodeEntry(draw_order, cs, arc_chain, false)); } CullState::direct_const_iterator di; for (di = cs->direct_begin(); di != cs->direct_end(); ++di) { - Node *node = (*di); - nassertv(node != (Node *)NULL); - _node_entries.insert(NodeEntry(draw_order, cs, node, true)); + const ArcChain &arc_chain = (*di); + _node_entries.insert(NodeEntry(draw_order, cs, arc_chain, true)); } } diff --git a/panda/src/cull/geomBinFixed.h b/panda/src/cull/geomBinFixed.h index db4da1ed7c..90299100ed 100644 --- a/panda/src/cull/geomBinFixed.h +++ b/panda/src/cull/geomBinFixed.h @@ -37,7 +37,7 @@ private: class NodeEntry { public: INLINE NodeEntry(int draw_order, const PT(CullState) &state, - Node *node, bool is_direct); + const ArcChain &arc_chain, bool is_direct); INLINE NodeEntry(const NodeEntry ©); INLINE void operator = (const NodeEntry ©); @@ -48,7 +48,7 @@ private: private: int _draw_order; PT(CullState) _state; - Node *_node; + ArcChain _arc_chain; bool _is_direct; }; diff --git a/panda/src/cull/geomBinUnsorted.cxx b/panda/src/cull/geomBinUnsorted.cxx index fbdd8f848b..c2db6940c2 100644 --- a/panda/src/cull/geomBinUnsorted.cxx +++ b/panda/src/cull/geomBinUnsorted.cxx @@ -90,26 +90,24 @@ draw(CullTraverser *trav) { CullState::geom_iterator gi; for (gi = cs->geom_begin(); gi != cs->geom_end(); ++gi) { - GeomNode *geom = (*gi); - nassertv(geom != (GeomNode *)NULL); + const ArcChain &arc_chain = (*gi); + nassertv(!arc_chain.empty()); + GeomNode *geom_node; + DCAST_INTO_V(geom_node, arc_chain.back()->get_child()); if (cull_cat.is_spam()) { cull_cat.spam() - << "Drawing " << *geom << "\n"; + << "Drawing " << *geom_node << "\n"; } - geom->draw(gsg); + geom_node->draw(gsg); } } CullState::direct_iterator di; for (di = cs->direct_begin(); di != cs->direct_end(); ++di) { - Node *node = (*di); - nassertv(node != (Node *)NULL); + const ArcChain &arc_chain = (*di); + nassertv(!arc_chain.empty()); - if (cull_cat.is_spam()) { - cull_cat.spam() - << "Drawing direct: " << *node << "\n"; - } - trav->draw_direct(node, cs->get_attributes()); + trav->draw_direct(arc_chain, cs->get_attributes()); } } } diff --git a/panda/src/display/graphicsStateGuardian.I b/panda/src/display/graphicsStateGuardian.I index 9bca29c955..2b230cd992 100644 --- a/panda/src/display/graphicsStateGuardian.I +++ b/panda/src/display/graphicsStateGuardian.I @@ -49,7 +49,7 @@ get_state() const { // projection node (i.e. the camera) for this scene, as // set by the last call to render_subgraph(). //////////////////////////////////////////////////////////////////// -INLINE const ProjectionNode *GraphicsStateGuardian:: +INLINE ProjectionNode *GraphicsStateGuardian:: get_current_projection_node(void) const { return _current_projection_node; } diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index d177a2b239..1a1a4708b1 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -68,10 +68,10 @@ public: virtual void prepare_display_region()=0; virtual void render_frame(const AllAttributesWrapper &initial_state)=0; - virtual void render_scene(Node *root, const ProjectionNode *projnode, + virtual void render_scene(Node *root, ProjectionNode *projnode, const AllAttributesWrapper &initial_state)=0; virtual void render_subgraph(RenderTraverser *traverser, - Node *subgraph, const ProjectionNode *projnode, + Node *subgraph, ProjectionNode *projnode, const AllAttributesWrapper &initial_state, const AllTransitionsWrapper &net_trans)=0; virtual void render_subgraph(RenderTraverser *traverser, @@ -99,7 +99,7 @@ public: RenderBuffer get_render_buffer(int buffer_type); - INLINE const ProjectionNode* get_current_projection_node(void) const ; + INLINE ProjectionNode *get_current_projection_node(void) const ; INLINE const Node* get_current_root_node(void) const; INLINE CPT(DisplayRegion) get_current_display_region(void) const; @@ -144,7 +144,7 @@ protected: // These must be set by render_scene(). Node *_current_root_node; - const ProjectionNode *_current_projection_node; + ProjectionNode *_current_projection_node; CPT(DisplayRegion) _current_display_region; // This is used by wants_normals() diff --git a/panda/src/dxgsg/dxGraphicsStateGuardian.cxx b/panda/src/dxgsg/dxGraphicsStateGuardian.cxx index a91f549223..62fb71ce3e 100644 --- a/panda/src/dxgsg/dxGraphicsStateGuardian.cxx +++ b/panda/src/dxgsg/dxGraphicsStateGuardian.cxx @@ -875,7 +875,7 @@ render_frame(const AllAttributesWrapper &initial_state) { // may be modified during rendering. //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian:: -render_scene(Node *root, const ProjectionNode *projnode, +render_scene(Node *root, ProjectionNode *projnode, const AllAttributesWrapper &initial_state) { #ifdef GSG_VERBOSE _pass_number = 0; @@ -905,11 +905,11 @@ render_scene(Node *root, const ProjectionNode *projnode, //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian:: render_subgraph(RenderTraverser *traverser, - Node *subgraph, const ProjectionNode *projnode, + Node *subgraph, ProjectionNode *projnode, const AllAttributesWrapper &initial_state, const AllTransitionsWrapper &net_trans) { activate(); - const ProjectionNode *old_projection_node = _current_projection_node; + ProjectionNode *old_projection_node = _current_projection_node; _current_projection_node = projnode; LMatrix4f old_projection_mat = _current_projection_mat; diff --git a/panda/src/dxgsg/dxGraphicsStateGuardian.h b/panda/src/dxgsg/dxGraphicsStateGuardian.h index 0104acdbcc..79fd538ee1 100644 --- a/panda/src/dxgsg/dxGraphicsStateGuardian.h +++ b/panda/src/dxgsg/dxGraphicsStateGuardian.h @@ -85,10 +85,10 @@ public: virtual void prepare_display_region(); virtual void render_frame(const AllAttributesWrapper &initial_state); - virtual void render_scene(Node *root, const ProjectionNode *projnode, + virtual void render_scene(Node *root, ProjectionNode *projnode, const AllAttributesWrapper &initial_state); virtual void render_subgraph(RenderTraverser *traverser, - Node *subgraph, const ProjectionNode *projnode, + Node *subgraph, ProjectionNode *projnode, const AllAttributesWrapper &initial_state, const AllTransitionsWrapper &net_trans); virtual void render_subgraph(RenderTraverser *traverser, diff --git a/panda/src/effects/lensFlareNode.cxx b/panda/src/effects/lensFlareNode.cxx index 71e3bb395f..6b2ed5bd76 100644 --- a/panda/src/effects/lensFlareNode.cxx +++ b/panda/src/effects/lensFlareNode.cxx @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -295,15 +296,14 @@ render_children(const vector_relation &arcs, const AllAttributesWrapper &attrib, //////////////////////////////////////////////////////////////////// bool LensFlareNode:: sub_render(const AllAttributesWrapper &attrib, AllTransitionsWrapper &trans, - GraphicsStateGuardianBase *gsgbase) -{ - GraphicsStateGuardian *gsg = DCAST(GraphicsStateGuardian, gsgbase); + RenderTraverser *trav) { + GraphicsStateGuardian *gsg = trav->get_gsg(); nassertr(_light_node != (Node*) NULL, false); //First we need the light position - const ProjectionNode *camera_node = gsg->get_current_projection_node(); - const PerspectiveProjection *pp = DCAST(PerspectiveProjection, camera_node->get_projection()); + ProjectionNode *camera_node = gsg->get_current_projection_node(); + PerspectiveProjection *pp = DCAST(PerspectiveProjection, camera_node->get_projection()); LPoint3f light_pos = get_rel_pos(_light_node, camera_node); diff --git a/panda/src/effects/lensFlareNode.h b/panda/src/effects/lensFlareNode.h index f9ee48b0a6..a0bd0cc021 100644 --- a/panda/src/effects/lensFlareNode.h +++ b/panda/src/effects/lensFlareNode.h @@ -38,8 +38,9 @@ PUBLISHED: INLINE void set_light_source(PT_Node source); public: - virtual bool sub_render(const AllAttributesWrapper &attrib, AllTransitionsWrapper &trans, - GraphicsStateGuardianBase *gsgbase); + virtual bool sub_render(const AllAttributesWrapper &attrib, + AllTransitionsWrapper &trans, + RenderTraverser *trav); virtual bool has_sub_render() const; private: diff --git a/panda/src/express/pointerTo.I b/panda/src/express/pointerTo.I index 6faa014175..1ba12071e4 100644 --- a/panda/src/express/pointerTo.I +++ b/panda/src/express/pointerTo.I @@ -50,9 +50,12 @@ template void PointerToBase:: reassign(To *ptr) { if (ptr != _ptr) { - if (_ptr != (To *)NULL) { - unref_delete(_ptr); - } + // First save the old pointer; we won't delete it until we have + // assigned the new one. We do this just in case there are + // cascading effects from deleting this pointer that might + // inadvertently delete the new one. (Don't laugh--it's + // happened!) + To *old_ptr = _ptr; _ptr = ptr; if (_ptr != (To *)NULL) { @@ -72,6 +75,11 @@ reassign(To *ptr) { } #endif } + + // Now delete the old pointer. + if (old_ptr != (To *)NULL) { + unref_delete(old_ptr); + } } } diff --git a/panda/src/express/referenceCount.I b/panda/src/express/referenceCount.I index b9a2a75c6f..eddeaa50ca 100644 --- a/panda/src/express/referenceCount.I +++ b/panda/src/express/referenceCount.I @@ -125,7 +125,6 @@ prepare_delete() { _ref_count = -100; } -#ifdef NDEBUG //////////////////////////////////////////////////////////////////// // Function: ReferenceCount::unref_consider_delete // Access: Public @@ -143,7 +142,6 @@ unref_consider_delete() { unref(); return (get_ref_count() == 0); } -#endif //////////////////////////////////////////////////////////////////// // Function: ReferenceCount::get_ref_count @@ -291,6 +289,16 @@ template INLINE void unref_delete(RefCountType *ptr) { if (((ReferenceCount *)ptr)->unref_consider_delete()) { +#ifndef NDEBUG + if (get_leak_memory()) { + // In leak-memory mode, we don't actually delete the pointer, + // although we do call the destructor explicitly. This has + // exactly the same effect as deleting it, without actually + // freeing up the memory it uses. + ptr->~RefCountType(); + return; + } +#endif delete ptr; } } diff --git a/panda/src/express/referenceCount.cxx b/panda/src/express/referenceCount.cxx index b00570146b..b2aa1d4e90 100644 --- a/panda/src/express/referenceCount.cxx +++ b/panda/src/express/referenceCount.cxx @@ -6,35 +6,3 @@ #include "referenceCount.h" TypeHandle ReferenceCount::_type_handle; - -#ifndef NDEBUG -//////////////////////////////////////////////////////////////////// -// Function: ReferenceCount::unref_consider_delete -// Access: Public -// Description: This function is called by the global unref_delete() -// function. This function unrefs the pointer and -// returns true if it should be deleted (i.e. the count -// has gone to zero), or false otherwise. It doesn't -// delete itself because (a) a method cannot safely -// delete this, and (b) we don't have a virtual -// destructor anyway. The decision of whether to delete -// is left up to unref_delete(). -//////////////////////////////////////////////////////////////////// -bool ReferenceCount:: -unref_consider_delete() { - unref(); - - if (get_leak_memory()) { - // In leak-memory mode, we don't actually delete anything. - // However, we do want to call prepare_delete() when the count - // reaches zero, to reset the refcount to -100 as a deleted flag. - if (get_ref_count() == 0) { - prepare_delete(); - MemoryUsage::remove_pointer(this); - } - return false; - } - - return (get_ref_count() == 0); -} -#endif diff --git a/panda/src/express/referenceCount.h b/panda/src/express/referenceCount.h index fdbe4373cb..3aef81e268 100644 --- a/panda/src/express/referenceCount.h +++ b/panda/src/express/referenceCount.h @@ -19,6 +19,7 @@ #include "typeHandle.h" #include "memoryUsage.h" +#include "config_express.h" #include @@ -44,13 +45,7 @@ public: // These functions are not part of the normal API, but they have to // be public. You shouldn't generally call these directly. INLINE void prepare_delete(); -#ifdef NDEBUG - // unref_consider_delete() is inline only if we are compiling - // NDEBUG. INLINE bool unref_consider_delete(); -#else - bool unref_consider_delete(); -#endif PUBLISHED: INLINE int get_ref_count() const; diff --git a/panda/src/glgsg/glGraphicsStateGuardian.cxx b/panda/src/glgsg/glGraphicsStateGuardian.cxx index 76430f6a81..d987f5c36d 100644 --- a/panda/src/glgsg/glGraphicsStateGuardian.cxx +++ b/panda/src/glgsg/glGraphicsStateGuardian.cxx @@ -554,7 +554,7 @@ render_frame(const AllAttributesWrapper &initial_state) { // may be modified during rendering. //////////////////////////////////////////////////////////////////// void GLGraphicsStateGuardian:: -render_scene(Node *root, const ProjectionNode *projnode, +render_scene(Node *root, ProjectionNode *projnode, const AllAttributesWrapper &initial_state) { #ifdef GSG_VERBOSE _pass_number = 0; @@ -584,7 +584,7 @@ render_scene(Node *root, const ProjectionNode *projnode, //////////////////////////////////////////////////////////////////// void GLGraphicsStateGuardian:: render_subgraph(RenderTraverser *traverser, - Node *subgraph, const ProjectionNode *projnode, + Node *subgraph, ProjectionNode *projnode, const AllAttributesWrapper &initial_state, const AllTransitionsWrapper &net_trans) { // Calling activate() frequently seems to be intolerably expensive @@ -593,7 +593,7 @@ render_subgraph(RenderTraverser *traverser, // activate(); - const ProjectionNode *old_projection_node = _current_projection_node; + ProjectionNode *old_projection_node = _current_projection_node; _current_projection_node = projnode; LMatrix4f old_projection_mat = _current_projection_mat; diff --git a/panda/src/glgsg/glGraphicsStateGuardian.h b/panda/src/glgsg/glGraphicsStateGuardian.h index 06baacbb7e..547b2bdafe 100644 --- a/panda/src/glgsg/glGraphicsStateGuardian.h +++ b/panda/src/glgsg/glGraphicsStateGuardian.h @@ -62,10 +62,10 @@ public: virtual void prepare_display_region(); virtual void render_frame(const AllAttributesWrapper &initial_state); - virtual void render_scene(Node *root, const ProjectionNode *projnode, + virtual void render_scene(Node *root, ProjectionNode *projnode, const AllAttributesWrapper &initial_state); virtual void render_subgraph(RenderTraverser *traverser, - Node *subgraph, const ProjectionNode *projnode, + Node *subgraph, ProjectionNode *projnode, const AllAttributesWrapper &initial_state, const AllTransitionsWrapper &net_trans); virtual void render_subgraph(RenderTraverser *traverser, diff --git a/panda/src/graph/Sources.pp b/panda/src/graph/Sources.pp index 896ca26d01..7caec6e891 100644 --- a/panda/src/graph/Sources.pp +++ b/panda/src/graph/Sources.pp @@ -9,12 +9,19 @@ allAttributesWrapper.I allAttributesWrapper.cxx \ allAttributesWrapper.h allTransitionsWrapper.I \ allTransitionsWrapper.cxx allTransitionsWrapper.h \ - bitMask32Transition.cxx bitMask32Transition.h boundedObject.I \ + arcChain.I arcChain.cxx arcChain.h \ + bitMask32Transition.cxx bitMask32Transition.h \ + bitMaskAttribute.I bitMaskAttribute.h \ + bitMaskTransition.I bitMaskTransition.h \ + boundedObject.I \ boundedObject.N boundedObject.cxx boundedObject.h config_graph.cxx \ config_graph.h graphReducer.cxx graphReducer.h immediateAttribute.I \ immediateAttribute.cxx immediateAttribute.h immediateTransition.I \ immediateTransition.cxx immediateTransition.h \ - lmatrix4fTransition.cxx lmatrix4fTransition.h multiNodeAttribute.I \ + lmatrix4fTransition.cxx lmatrix4fTransition.h \ + matrixAttribute.I matrixAttribute.h matrixTransition.I \ + matrixTransition.h \ + multiNodeAttribute.I \ multiNodeAttribute.cxx multiNodeAttribute.h multiNodeTransition.I \ multiNodeTransition.cxx multiNodeTransition.h namedNode.I \ namedNode.cxx namedNode.h node.I node.cxx node.h nodeAttribute.I \ @@ -36,11 +43,14 @@ onOffTransition.I onOffTransition.cxx onOffTransition.h \ onTransition.I onTransition.cxx onTransition.h pt_NamedNode.N \ pt_NamedNode.cxx pt_NamedNode.h pt_Node.N pt_Node.cxx pt_Node.h \ - vector_PT_Node.cxx vector_PT_Node.h + setTransitionHelpers.I setTransitionHelpers.h \ + traverserVisitor.I traverserVisitor.h \ + vector_PT_Node.cxx vector_PT_Node.h wrt.I wrt.h #define INSTALL_HEADERS \ allAttributesWrapper.I allAttributesWrapper.h \ allTransitionsWrapper.I allTransitionsWrapper.h \ + arcChain.I arcChain.h \ bitMask32Transition.h bitMaskAttribute.I bitMaskAttribute.h \ bitMaskTransition.I bitMaskTransition.h boundedObject.I \ boundedObject.h config_graph.h dftraverser.I dftraverser.h \ diff --git a/panda/src/graph/arcChain.I b/panda/src/graph/arcChain.I new file mode 100644 index 0000000000..72b33accd3 --- /dev/null +++ b/panda/src/graph/arcChain.I @@ -0,0 +1,219 @@ +// Filename: arcChain.I +// Created by: drose (05Jan01) +// +//////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////// +// Function: ArcChain::ArcComponent::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE ArcChain::ArcComponent:: +ArcComponent(NodeRelation *arc, ArcComponent *next) : + _arc(arc), + _next(next) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: ArcChain::ForwardIterator::Constructor +// Access: Public +// Description: This is an STL-style iterator that can be used to +// traverse the full list of arcs traversed so far by +// the ArcChain. Its primary purpose is as a +// parameter to wrt() so we can compute a correct +// relative wrt to the particular instance we've reached +// so far. +//////////////////////////////////////////////////////////////////// +INLINE ArcChain::ForwardIterator:: +ForwardIterator(ArcChain::ArcComponent *comp) : _comp(comp) { +} + +//////////////////////////////////////////////////////////////////// +// Function: ArcChain::ForwardIterator::Dereference Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE NodeRelation *ArcChain::ForwardIterator:: +operator * () const { + nassertr(_comp != (ArcComponent *)NULL, NULL); + return _comp->_arc; +} + +//////////////////////////////////////////////////////////////////// +// Function: ArcChain::ForwardIterator::Increment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void ArcChain::ForwardIterator:: +operator ++() { + nassertv(_comp != (ArcComponent *)NULL); + _comp = _comp->_next; +} + +//////////////////////////////////////////////////////////////////// +// Function: ArcChain::ForwardIterator::Equality Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool ArcChain::ForwardIterator:: +operator == (const ArcChain::ForwardIterator &other) const { + return _comp == other._comp; +} + +//////////////////////////////////////////////////////////////////// +// Function: ArcChain::ForwardIterator::Inequality Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool ArcChain::ForwardIterator:: +operator != (const ArcChain::ForwardIterator &other) const { + return _comp != other._comp; +} + +//////////////////////////////////////////////////////////////////// +// Function: ArcChain::Default Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE ArcChain:: +ArcChain() { +} + +//////////////////////////////////////////////////////////////////// +// Function: ArcChain::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE ArcChain:: +ArcChain(const ArcChain ©) : + _head(copy._head) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: ArcChain::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void ArcChain:: +operator = (const ArcChain ©) { + _head = copy._head; +} + +//////////////////////////////////////////////////////////////////// +// Function: ArcChain::begin +// Access: Public +// Description: Returns an iterator that can be used to traverse the +// list of arcs. +//////////////////////////////////////////////////////////////////// +INLINE ArcChain::const_iterator ArcChain:: +begin() const { + return ForwardIterator(_head); +} + +//////////////////////////////////////////////////////////////////// +// Function: ArcChain::end +// Access: Public +// Description: Returns an iterator that can be used to traverse the +// list of arcs. +//////////////////////////////////////////////////////////////////// +INLINE ArcChain::const_iterator ArcChain:: +end() const { + return ForwardIterator(); +} + +//////////////////////////////////////////////////////////////////// +// Function: ArcChain::empty +// Access: Public +// Description: Returns true if the list of arcs returned by begin() +// .. end() is empty (i.e. begin() == end()), false +// otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool ArcChain:: +empty() const { + return (_head == (ArcComponent *)NULL); +} + +//////////////////////////////////////////////////////////////////// +// Function: ArcChain::push_back +// Access: Public +// Description: Appends the indicated arc onto the end of the chain. +//////////////////////////////////////////////////////////////////// +INLINE void ArcChain:: +push_back(NodeRelation *arc) { + _head = new ArcComponent(arc, _head); +} + +//////////////////////////////////////////////////////////////////// +// Function: ArcChain::pop_back +// Access: Public +// Description: Removes the last arc from the end of the chain. +//////////////////////////////////////////////////////////////////// +INLINE void ArcChain:: +pop_back() { + nassertv(_head != (ArcComponent *)NULL); + _head = _head->_next; +} + +//////////////////////////////////////////////////////////////////// +// Function: ArcChain::back +// Access: Public +// Description: Returns the last arc in the chain. +//////////////////////////////////////////////////////////////////// +INLINE NodeRelation *ArcChain:: +back() const { + nassertr(_head != (ArcComponent *)NULL, (NodeRelation *)NULL); + return _head->_arc; +} + +//////////////////////////////////////////////////////////////////// +// Function: ArcChain::operator == +// Access: Public +// Description: Returns true if the two chains are equivalent; that +// is, if they contain the same list of arcs in the same +// order. +//////////////////////////////////////////////////////////////////// +INLINE bool ArcChain:: +operator == (const ArcChain &other) const { + return (compare_to(other) == 0); +} + +//////////////////////////////////////////////////////////////////// +// Function: ArcChain::operator != +// Access: Public +// Description: Returns true if the two chains are not equivalent. +//////////////////////////////////////////////////////////////////// +INLINE bool ArcChain:: +operator != (const ArcChain &other) const { + return !operator == (other); +} + +//////////////////////////////////////////////////////////////////// +// Function: ArcChain::operator < +// Access: Public +// Description: Returns true if this ArcChain sorts before the other +// one, false otherwise. The sorting order of two +// nonequivalent ArcChains is consistent but undefined, +// and is useful only for storing ArcChains in a sorted +// container like an STL set. +//////////////////////////////////////////////////////////////////// +INLINE bool ArcChain:: +operator < (const ArcChain &other) const { + return (compare_to(other) < 0); +} + +//////////////////////////////////////////////////////////////////// +// Function: ArcChain::output +// Access: Public +// Description: Writes a sensible description of the ArcChain to the +// indicated output stream. +//////////////////////////////////////////////////////////////////// +INLINE void ArcChain:: +output(ostream &out) const { + if (empty()) { + out << "(empty)"; + } else { + r_output(out, _head); + } +} diff --git a/panda/src/graph/arcChain.cxx b/panda/src/graph/arcChain.cxx new file mode 100644 index 0000000000..6f97386976 --- /dev/null +++ b/panda/src/graph/arcChain.cxx @@ -0,0 +1,79 @@ +// Filename: arcChain.cxx +// Created by: drose (05Jan01) +// +//////////////////////////////////////////////////////////////////// + +#include "arcChain.h" +#include "node.h" +#include "namedNode.h" + +//////////////////////////////////////////////////////////////////// +// Function: ArcChain::compare_to +// Access: Public +// Description: Returns a number less than zero if this ArcChain +// sorts before the other one, greater than zero if it +// sorts after, or zero if they are equivalent. +// +// Two ArcChains are considered equivalent if they +// consist of exactly the same list of arcs in the same +// order. Otherwise, they are different; different +// ArcChains will be ranked in a consistent but +// undefined ordering; the ordering is useful only for +// placing the ArcChains in a sorted container like an +// STL set. +//////////////////////////////////////////////////////////////////// +int ArcChain:: +compare_to(const ArcChain &other) const { + ArcComponent *a = _head; + ArcComponent *b = other._head; + + while (a != (ArcComponent *)NULL && b != (ArcComponent *)NULL) { + if (a < b) { + return -1; + } else if (a > b) { + return 1; + } + + a = a->_next; + b = b->_next; + } + + if (a < b) { + return -1; + } else if (a > b) { + return 1; + } + + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: ArcChain::r_output +// Access: Private +// Description: The recursive implementation of output(), this writes +// the names of each arc component in order from +// beginning to end, by first walking to the end of the +// linked list and then outputting from there. +//////////////////////////////////////////////////////////////////// +void ArcChain:: +r_output(ostream &out, ArcComponent *comp) const { + ArcComponent *next = comp->_next; + if (next != (ArcComponent *)NULL) { + // This is not the head of the list; keep going up. + r_output(out, next); + out << "/"; + } + + // Now output this component. + Node *node = comp->_arc->get_child(); + if (node->is_of_type(NamedNode::get_class_type())) { + NamedNode *named_node = DCAST(NamedNode, node); + if (named_node->has_name()) { + out << named_node->get_name(); + } else { + out << node->get_type(); + } + } else { + out << node->get_type(); + } +} diff --git a/panda/src/graph/arcChain.h b/panda/src/graph/arcChain.h new file mode 100644 index 0000000000..751e344695 --- /dev/null +++ b/panda/src/graph/arcChain.h @@ -0,0 +1,105 @@ +// Filename: arcChain.h +// Created by: drose (05Jan01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef ARCCHAIN_H +#define ARCCHAIN_H + +#include + +#include "nodeRelation.h" + +#include +#include +#include + +//////////////////////////////////////////////////////////////////// +// Class : ArcChain +// Description : This defines a singly-linked chain of arcs from one +// point (e.g. the root of the scene graph) to another +// point (e.g. a leaf), although no assumption is made +// about the relationship between the arcs. It is +// simply a list of arcs that may only be lengthened or +// shortened, or copied. +// +// This list may be copied by reference using the copy +// constructor; the new copy may be appended to without +// modifying the source (but individual nodes may not be +// modified). +// +// This serves as the fundamental implementation of +// NodePaths, for instance, and also is used during +// render traversals to manage the list of arcs +// traversed so far (and thus compute unambiguous +// wrt's). +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA ArcChain { +private: + // We maintain our own linked list structure here instead of using + // some STL structure, so we can efficiently copy-construct these + // things by sharing the initial part of the list. + + // We have a singly-linked list whose head is the bottom arc of the + // path, and whose tail is the top arc of the path. Thus, we can + // copy the entire path by simply copying the head pointer, and we + // can then append to or shorten our own path without affecting the + // paths we're sharing ArcComponents with. Very LISPy. + class ArcComponent : public ReferenceCount { + public: + INLINE ArcComponent(NodeRelation *arc, ArcComponent *next); + PT(NodeRelation) _arc; + PT(ArcComponent) _next; + }; + + PT(ArcComponent) _head; + + // This is a supporting class for iterating through all the arcs via + // begin() .. end(). + class ForwardIterator { + public: + INLINE ForwardIterator(ArcComponent *comp = NULL); + INLINE NodeRelation *operator * () const; + INLINE void operator ++(); + INLINE bool operator == (const ForwardIterator &other) const; + INLINE bool operator != (const ForwardIterator &other) const; + + private: + ArcComponent *_comp; + }; + +public: + typedef ForwardIterator iterator; + typedef ForwardIterator const_iterator; + + INLINE ArcChain(); + INLINE ArcChain(const ArcChain ©); + INLINE void operator = (const ArcChain ©); + + INLINE const_iterator begin() const; + INLINE const_iterator end() const; + INLINE bool empty() const; + + INLINE void push_back(NodeRelation *arc); + INLINE void pop_back(); + INLINE NodeRelation *back() const; + + INLINE bool operator == (const ArcChain &other) const; + INLINE bool operator != (const ArcChain &other) const; + INLINE bool operator < (const ArcChain &other) const; + int compare_to(const ArcChain &other) const; + + INLINE void output(ostream &out) const; + +private: + void r_output(ostream &out, ArcComponent *comp) const; +}; + +INLINE ostream &operator << (ostream &out, const ArcChain &arc_chain) { + arc_chain.output(out); + return out; +} + +#include "arcChain.I" + +#endif diff --git a/panda/src/graph/config_graph.cxx b/panda/src/graph/config_graph.cxx index a57c077485..0c8ba067d8 100644 --- a/panda/src/graph/config_graph.cxx +++ b/panda/src/graph/config_graph.cxx @@ -49,9 +49,16 @@ ConfigureFn(config_graph) { // wrt(), so that the second time wrt() is called on a particular // node-node pair it will be much cheaper than the first time. This // is the default behavior; you'd only want to turn it off if for some -// reason it was broken. +// reason it was broken. This is true by default and cannot be turned +// off in optimized (NDEBUG) mode. const bool cache_wrt = config_graph.GetBool("cache-wrt", true); +// Set this true to force abort() to be called if an ambiguous wrt() +// call is made. This will hopefully allow the programmer to get a +// stack dump and determine who is issuing the ambiguous wrt(). This +// cannot be turned on in optimized (NDEBUG) mode. +const bool ambiguous_wrt_abort = config_graph.GetBool("ambiguous-wrt-abort", false); + // Set this true to double-check the cached value of wrt(), above, by // performing an explicit uncached wrt() and comparing the results. // Obviously very slow. This cannot be turned on in optimized diff --git a/panda/src/graph/config_graph.h b/panda/src/graph/config_graph.h index f2a0ef5024..0d49f3a465 100644 --- a/panda/src/graph/config_graph.h +++ b/panda/src/graph/config_graph.h @@ -14,6 +14,7 @@ NotifyCategoryDecl(wrt, EXPCL_PANDA, EXPTP_PANDA); // Configure variables for graph package. extern const bool EXPCL_PANDA cache_wrt; +extern const bool EXPCL_PANDA ambiguous_wrt_abort; extern const bool EXPCL_PANDA paranoid_wrt; extern const bool EXPCL_PANDA paranoid_graph; diff --git a/panda/src/graph/matrixTransition.I b/panda/src/graph/matrixTransition.I index e33cc6787c..825c3eb6a4 100644 --- a/panda/src/graph/matrixTransition.I +++ b/panda/src/graph/matrixTransition.I @@ -176,8 +176,17 @@ internal_compare_to(const NodeTransition *other) const { const MatrixTransition *ot; DCAST_INTO_R(ot, other, false); - // return _matrix.compare_to(ot->_matrix); - return this - other; + // Should we bother comparing matrices componentwise, or should we + // just assume that any two different Matrix pointers are probably + // different matrices? + + // For now, we compare componentwise. It makes paranoid_wrt more + // sensible, and it doesn't seem to make a big different to + // performance. + return _matrix.compare_to(ot->_matrix, 0.001); + + // Uncomment this line instead to compare matrices pointerwise. + // return this - other; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/graph/node.cxx b/panda/src/graph/node.cxx index f720df310b..ed4bb9b74f 100644 --- a/panda/src/graph/node.cxx +++ b/panda/src/graph/node.cxx @@ -232,7 +232,7 @@ get_child(TypeHandle type, int index) const { //////////////////////////////////////////////////////////////////// bool Node:: sub_render(const AllAttributesWrapper &, AllTransitionsWrapper &, - GraphicsStateGuardianBase *) { + RenderTraverser *) { return true; } diff --git a/panda/src/graph/node.h b/panda/src/graph/node.h index 0a8720a777..3eecc69a9e 100644 --- a/panda/src/graph/node.h +++ b/panda/src/graph/node.h @@ -15,7 +15,7 @@ #include class NodeAttributes; -class GraphicsStateGuardianBase; +class RenderTraverser; class AllAttributesWrapper; class AllTransitionsWrapper; class BamWriter; @@ -70,7 +70,7 @@ public: // It may or may not intercept the render traversal. virtual bool sub_render(const AllAttributesWrapper &attrib, AllTransitionsWrapper &trans, - GraphicsStateGuardianBase *gsgbase); + RenderTraverser *trav); virtual bool has_sub_render() const; PUBLISHED: diff --git a/panda/src/graph/nodeRelation.I b/panda/src/graph/nodeRelation.I index 527130651a..839f78cdf3 100644 --- a/panda/src/graph/nodeRelation.I +++ b/panda/src/graph/nodeRelation.I @@ -315,6 +315,20 @@ compare_transitions_to(const NodeRelation *arc) const { return _transitions.compare_to(arc->_transitions); } +//////////////////////////////////////////////////////////////////// +// Function: NodeRelation::get_last_update +// Access: Public +// Description: Returns the sequence number associated with the last +// time this arc was changed, for instance to change its +// state or to reparent it. The only sensible thing you +// can do with this is store it and note whether it +// increases. +//////////////////////////////////////////////////////////////////// +INLINE UpdateSeq NodeRelation:: +get_last_update() const { + return _last_update; +} + //////////////////////////////////////////////////////////////////// // Function: NodeRelation::create_typed_arc // Access: Public, Static diff --git a/panda/src/graph/nodeRelation.cxx b/panda/src/graph/nodeRelation.cxx index 2274a443c7..e275c75553 100644 --- a/panda/src/graph/nodeRelation.cxx +++ b/panda/src/graph/nodeRelation.cxx @@ -382,11 +382,11 @@ compose_transitions_from(const NodeTransitions &trans) { bool NodeRelation:: sub_render_trans(const AllAttributesWrapper &attrib, AllTransitionsWrapper &trans, - GraphicsStateGuardianBase *gsgbase) { + RenderTraverser *trav) { bool all_true = true; NodeTransitions::const_iterator ti; for (ti = _transitions.begin(); ti != _transitions.end(); ++ti) { - if (!(*ti).second->sub_render(this, attrib, trans, gsgbase)) { + if (!(*ti).second->sub_render(this, attrib, trans, trav)) { all_true = false; } } @@ -449,7 +449,7 @@ attach() { // Blow out the cache and increment the current update sequence. _net_transitions.clear(); - ++last_graph_update[_type]; + _last_update = ++last_graph_update[_type]; _parent->force_bound_stale(); mark_bound_stale(); @@ -491,7 +491,7 @@ detach() { // Blow out the cache and increment the current update sequence. _net_transitions.clear(); - ++last_graph_update[_type]; + _last_update = ++last_graph_update[_type]; return result; } @@ -522,7 +522,7 @@ detach_below() { // Blow out the cache and increment the current update sequence. _net_transitions.clear(); - ++last_graph_update[_type]; + _last_update = ++last_graph_update[_type]; return result; } @@ -544,7 +544,7 @@ changed_transition(TypeHandle trans_type) { if (_net_transitions != (NodeTransitionCache *)NULL) { _net_transitions->clear_transition(trans_type); } - last_graph_update[get_type()]++; + _last_update = ++last_graph_update[get_type()]; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/graph/nodeRelation.h b/panda/src/graph/nodeRelation.h index e3c717555b..43ea9dfafb 100644 --- a/panda/src/graph/nodeRelation.h +++ b/panda/src/graph/nodeRelation.h @@ -102,10 +102,12 @@ PUBLISHED: INLINE int compare_transitions_to(const NodeRelation *arc) const; + INLINE UpdateSeq get_last_update() const; + public: bool sub_render_trans(const AllAttributesWrapper &attrib, AllTransitionsWrapper &trans, - GraphicsStateGuardianBase *gsgbase); + RenderTraverser *trav); bool has_sub_render_trans() const; public: @@ -154,6 +156,12 @@ private: PT(NodeTransitionCache) _net_transitions; Node *_top_subtree; + // This is updated with the current update sequence each time the + // arc is changed (for instance, to change its state or to reparent + // it or something). It exists to support caching in the cull + // traversal. + UpdateSeq _last_update; + public: static void register_with_read_factory(void); virtual void write_datagram(BamWriter* manager, Datagram &me); diff --git a/panda/src/graph/nodeTransition.cxx b/panda/src/graph/nodeTransition.cxx index 28c90cb149..0364f37510 100644 --- a/panda/src/graph/nodeTransition.cxx +++ b/panda/src/graph/nodeTransition.cxx @@ -36,7 +36,7 @@ get_handle() const { //////////////////////////////////////////////////////////////////// bool NodeTransition:: sub_render(NodeRelation *, const AllAttributesWrapper &, - AllTransitionsWrapper &, GraphicsStateGuardianBase *) { + AllTransitionsWrapper &, RenderTraverser *) { return true; } diff --git a/panda/src/graph/nodeTransition.h b/panda/src/graph/nodeTransition.h index bd6da30848..c26afceac1 100644 --- a/panda/src/graph/nodeTransition.h +++ b/panda/src/graph/nodeTransition.h @@ -15,7 +15,7 @@ class NodeAttribute; class NodeAttributes; class NodeTransitions; class NodeRelation; -class GraphicsStateGuardianBase; +class RenderTraverser; class AllAttributesWrapper; class AllTransitionsWrapper; class BamWriter; @@ -67,7 +67,7 @@ public: virtual bool sub_render(NodeRelation *arc, const AllAttributesWrapper &attrib, AllTransitionsWrapper &trans, - GraphicsStateGuardianBase *gsgbase); + RenderTraverser *trav); virtual bool has_sub_render() const; virtual void output(ostream &out) const; diff --git a/panda/src/graph/wrt.I b/panda/src/graph/wrt.I index ae69ce1f66..fbe8ea1818 100644 --- a/panda/src/graph/wrt.I +++ b/panda/src/graph/wrt.I @@ -1,13 +1,8 @@ -// Filename: wrt.cxx +// Filename: wrt.I // Created by: drose (26Oct98) // //////////////////////////////////////////////////////////////////// -#include "wrt.h" -#include "nodeRelation.h" -#include "node.h" -#include "config_graph.h" - //////////////////////////////////////////////////////////////////// // Function: get_cached_net_transition // Description: Returns the net transition from the root of the @@ -148,10 +143,27 @@ get_cached_net_transition(const Node *node, } if (parent_arc == (NodeRelation *)NULL) { +#ifndef NDEBUG // No, it wasn't mentioned. Issue a warning and use the first // one. - graph_cat.warning() - << *node << " has multiple parents; wrt() ambiguous.\n"; + if (graph_cat.is_warning()) { + graph_cat.warning() + << *node << " has " << urp.size() << " parents; wrt() ambiguous.\n" + << " parents are: "; + UpRelationPointers::const_iterator urpi; + urpi = urp.begin(); + graph_cat.warning(false) << *(*urpi)->get_parent(); + urpi++; + while (urpi != urp.end()) { + graph_cat.warning(false) << ", " << *(*urpi)->get_parent(); + urpi++; + } + graph_cat.warning(false) << "\n"; + } + if (ambiguous_wrt_abort) { + abort(); + } +#endif parent_arc = *(urp.begin()); } } @@ -172,6 +184,7 @@ get_cached_net_transition(const Node *node, } } +#ifndef NDEBUG //////////////////////////////////////////////////////////////////// // Function: get_uncached_net_transition // Description: Returns the net transition from the root of the graph @@ -238,10 +251,27 @@ get_uncached_net_transition(const Node *node, } if (parent_arc == (NodeRelation *)NULL) { +#ifndef NDEBUG // No, it wasn't mentioned. Issue a warning and use the first - // one. - graph_cat.warning() - << *node << " has multiple parents; wrt() ambiguous.\n"; + // one. + if (graph_cat.is_warning()) { + graph_cat.warning() + << *node << " has " << urp.size() << " parents; wrt() ambiguous.\n" + << " parents are:"; + UpRelationPointers::const_iterator urpi; + urpi = urp.begin(); + graph_cat.warning(false) << *(*urpi)->get_parent(); + urpi++; + while (urpi != urp.end()) { + graph_cat.warning(false) << ", " << *(*urpi)->get_parent(); + urpi++; + } + graph_cat.warning(false) << "\n"; + } + if (ambiguous_wrt_abort) { + abort(); + } +#endif parent_arc = *(urp.begin()); } } @@ -256,7 +286,7 @@ get_uncached_net_transition(const Node *node, result.compose_in_place(next); } - +#endif //////////////////////////////////////////////////////////////////// @@ -295,8 +325,11 @@ cached_wrt_base(const Node *from, if (check_from_trans.compare_to(net_from_trans) != 0) { graph_cat.warning() << "WRT cache from " << *from << " is invalid!\n" - << " cached value is " << net_from_trans << "\n" - << " should be " << check_from_trans << "\n"; + << " cached value is:\n"; + net_from_trans.write(graph_cat.warning(false), 4); + graph_cat.warning(false) + << " should be:\n"; + check_from_trans.write(graph_cat.warning(false), 4); net_from_trans = check_from_trans; } @@ -305,8 +338,11 @@ cached_wrt_base(const Node *from, if (check_to_trans.compare_to(result) != 0) { graph_cat.warning() << "WRT cache to " << *to << " is invalid!\n" - << " cached value is " << result << "\n" - << " should be " << check_to_trans << "\n"; + << " cached value is:\n"; + result.write(graph_cat.warning(false), 4); + graph_cat.warning(false) + << " should be:\n"; + check_to_trans.write(graph_cat.warning(false), 4); result = check_to_trans; } } @@ -315,6 +351,7 @@ cached_wrt_base(const Node *from, result.invert_compose_in_place(net_from_trans); } +#ifndef NDEBUG //////////////////////////////////////////////////////////////////// // Function: uncached_wrt_base // Description: The implementation of wrt_base, below, but never @@ -328,8 +365,6 @@ uncached_wrt_base(const Node *from, InputIterator2 to_arcs_begin, InputIterator2 to_arcs_end, TransitionWrapper &result, TypeHandle graph_type) { - // UpdateSeq now = last_graph_update[graph_type]; - TransitionWrapper net_from_trans = TransitionWrapper::init_from(result); get_uncached_net_transition(from, from_arcs_begin, from_arcs_end, net_from_trans, graph_type); @@ -337,6 +372,7 @@ uncached_wrt_base(const Node *from, result, graph_type); result.invert_compose_in_place(net_from_trans); } +#endif //////////////////////////////////////////////////////////////////// // Function: wrt_base @@ -362,15 +398,17 @@ wrt_base(const Node *from, InputIterator2 to_arcs_begin, InputIterator2 to_arcs_end, TransitionWrapper &result, TypeHandle graph_type) { - if (cache_wrt) { - cached_wrt_base(from, from_arcs_begin, from_arcs_end, - to, to_arcs_begin, to_arcs_end, - result, graph_type); - } else { +#ifndef NDEBUG + if (!cache_wrt) { uncached_wrt_base(from, from_arcs_begin, from_arcs_end, to, to_arcs_begin, to_arcs_end, result, graph_type); + return; } +#endif + cached_wrt_base(from, from_arcs_begin, from_arcs_end, + to, to_arcs_begin, to_arcs_end, + result, graph_type); } template @@ -417,6 +455,7 @@ wrt(const Node *from, result, graph_type); } +#ifndef NDEBUG template INLINE void uncached_wrt(const Node *from, const Node *to, @@ -458,17 +497,78 @@ uncached_wrt(const Node *from, to, to_arcs_begin, to_arcs_end, result, graph_type); } +#endif +#ifndef NDEBUG template Node * -wrt_subtree(NodeRelation *arc, Node *to, TransitionWrapper &result, - TypeHandle graph_type) { - if (!cache_wrt) { - // If we aren't caching wrt, do this the hard way. - uncached_wrt(arc->get_child(), &arc, &arc + 1, to, result, graph_type); +get_uncached_wrt_subtree(Node *node, Node *to, TransitionWrapper &result, + TypeHandle graph_type) { + nassertr(node != (Node *)NULL, to); + UpRelations::const_iterator uri; + uri = node->_parents.find(graph_type); + + if (uri == node->_parents.end()) { + // This node has no parents. Stop here. + result.make_identity(); return to; } + const UpRelationPointers &urp = (*uri).second; + if (urp.empty()) { + // Again, no parents. Stop here. + result.make_identity(); + return to; + } + + if (node == to) { + // We've reached our stopping point. Stop here. + result.make_identity(); + return node; + } + + if (urp.size() != 1) { + // There are multiple parents, so stop here. + result.make_identity(); + return node; + } + + const NodeRelation *parent_arc = *(urp.begin()); + + Node *stop = + get_uncached_wrt_subtree(parent_arc->get_parent(), to, + result, graph_type); + + TransitionWrapper next = TransitionWrapper::init_from(result); + next.extract_from(parent_arc); + + result.compose_in_place(next); + + return stop; +} + +template +INLINE Node * +uncached_wrt_subtree(NodeRelation *arc, Node *to, TransitionWrapper &result, + TypeHandle graph_type) { + Node *stop = + get_uncached_wrt_subtree(arc->get_parent(), to, + result, graph_type); + + TransitionWrapper next = TransitionWrapper::init_from(result); + next.extract_from(arc); + + result.compose_in_place(next); + + return stop; +} + +#endif + +template +Node * +cached_wrt_subtree(NodeRelation *arc, Node *to, TransitionWrapper &result, + TypeHandle graph_type) { UpdateSeq now = last_graph_update[graph_type]; // First, determine the net transition up to the top of the current @@ -507,8 +607,34 @@ wrt_subtree(NodeRelation *arc, Node *to, TransitionWrapper &result, // Now check the results. TransitionWrapper check_trans = TransitionWrapper::init_from(result); - uncached_wrt(arc->get_child(), &arc, &arc + 1, to, check_trans, - graph_type); + Node *top_subtree_3 = + uncached_wrt_subtree(arc, to, check_trans, graph_type); + + if (top_subtree_3 != top_subtree) { + graph_cat.warning() + << "WRT subtree cache from " << *arc->get_child() << " to "; + if (to == (Node *)NULL) { + graph_cat.warning(false) << "(top)"; + } else { + graph_cat.warning(false) << *to; + } + graph_cat.warning(false) + << " computes incorrect top_subtree!\n" + << " computed "; + if (top_subtree == (Node *)NULL) { + graph_cat.warning(false) << "(top)\n"; + } else { + graph_cat.warning(false) << *top_subtree << "\n"; + } + graph_cat.warning(false) + << " should be "; + if (top_subtree_3 == (Node *)NULL) { + graph_cat.warning(false) << "(top)\n"; + } else { + graph_cat.warning(false) << *top_subtree_3 << "\n"; + } + top_subtree = top_subtree_3; + } if (check_trans.compare_to(result) != 0) { graph_cat.warning() @@ -520,8 +646,11 @@ wrt_subtree(NodeRelation *arc, Node *to, TransitionWrapper &result, } graph_cat.warning(false) << " is invalid!\n" - << " cached value is " << result << "\n" - << " should be " << check_trans << "\n"; + << " cached value is:\n"; + result.write(graph_cat.warning(false), 4); + graph_cat.warning(false) + << " should be:\n"; + check_trans.write(graph_cat.warning(false), 4); result = check_trans; } } @@ -529,3 +658,18 @@ wrt_subtree(NodeRelation *arc, Node *to, TransitionWrapper &result, return top_subtree; } + +template +INLINE Node * +wrt_subtree(NodeRelation *arc, Node *to, TransitionWrapper &result, + TypeHandle graph_type) { +#ifndef NDEBUG + if (!cache_wrt) { + // If we aren't caching wrt, do this the hard way. + return uncached_wrt_subtree(arc, to, result, graph_type); + } +#endif + return cached_wrt_subtree(arc, to, result, graph_type); +} + + diff --git a/panda/src/graph/wrt.h b/panda/src/graph/wrt.h index 71fee63484..abee0f1507 100644 --- a/panda/src/graph/wrt.h +++ b/panda/src/graph/wrt.h @@ -8,6 +8,10 @@ #include +#include "nodeRelation.h" +#include "node.h" +#include "config_graph.h" + #include class Node; @@ -57,6 +61,7 @@ wrt(const Node *from, InputIterator2 to_arcs_begin, InputIterator2 to_arcs_end, TransitionWrapper &result, TypeHandle graph_type); +#ifndef NDEBUG // Similar to the above, but always uncached. Useful mainly for // debugging, or when you suspect the cache is invalid. Also note // that you can configure 'cache-wrt' or 'paranoid-wrt' to disable or @@ -87,17 +92,18 @@ uncached_wrt(const Node *from, const Node *to, InputIterator2 to_arcs_begin, InputIterator2 to_arcs_end, TransitionWrapper &result, TypeHandle graph_type); +#endif // The following function is a bit different. Rather than computing // the relative transform between two nodes, it computes the net -// transform along the shortest unambigous path from the indicated arc -// towards the root. That is, this is the wrt between the child of -// the indicated arc and the closest ancestor node that has multiple -// parents, or the root of the scene graph if the arc only appears -// once in the scene graph. The return value is the particular node -// with multiple parents at which the wrt stopped, or NULL if it went -// all the way to the root. +// transform along the shortest unambiguous path from the indicated +// arc towards the root. That is, this is the wrt between the child +// of the indicated arc and the closest ancestor node that has +// multiple parents, or the root of the scene graph if the arc only +// appears once in the scene graph. The return value is the +// particular node with multiple parents at which the wrt stopped, or +// NULL if it went all the way to the root. // This is extended just a bit further by allowing the user to specify // a "to" node. This must be either NULL, or the expected top node, @@ -113,7 +119,7 @@ uncached_wrt(const Node *from, // CullTraverser) that needs to cache a wrt-type value for many nodes // across the entire tree. template -Node * +INLINE Node * wrt_subtree(NodeRelation *arc, Node *to, TransitionWrapper &result, TypeHandle graph_type); diff --git a/panda/src/gui/guiManager.cxx b/panda/src/gui/guiManager.cxx index 29a3f11f26..b6a9cbeb93 100644 --- a/panda/src/gui/guiManager.cxx +++ b/panda/src/gui/guiManager.cxx @@ -18,7 +18,8 @@ GuiManager::GuiMap* GuiManager::_map = (GuiManager::GuiMap*)0L; -GuiManager* GuiManager::get_ptr(GraphicsWindow* w, MouseAndKeyboard* mak) { +GuiManager* GuiManager::get_ptr(GraphicsWindow* w, MouseAndKeyboard* mak, + Node *root2d) { GuiManager* ret; if (_map == (GuiMap*)0L) { if (gui_cat->is_debug()) @@ -83,30 +84,36 @@ GuiManager* GuiManager::get_ptr(GraphicsWindow* w, MouseAndKeyboard* mak) { << watcher->get_leave_pattern() << "' with 'gui-out-%r'" << endl; watcher->set_leave_pattern("gui-out-%r"); - // next, create a 2d layer for the GUI stuff to live in. - Node* root2d_top = new NamedNode("GUI_top"); - Node* root2d = new NamedNode("GUI"); - NodeRelation* root2d_arc = new RenderRelation(root2d_top, root2d); - root2d_arc->set_transition(new DepthTestTransition(DepthTestProperty::M_none), 1); - root2d_arc->set_transition(new DepthWriteTransition(DepthWriteTransition::off()), 1); - root2d_arc->set_transition(new LightTransition(LightTransition::all_off()), 1); - root2d_arc->set_transition(new MaterialTransition(MaterialTransition::off()), 1); - root2d_arc->set_transition(new CullFaceTransition(CullFaceProperty::M_cull_none), 1); - PT(Camera) cam = new Camera("GUI_cam"); - new RenderRelation(root2d, cam); - cam->set_scene(root2d_top); - Frustumf frust2d; - frust2d.make_ortho_2D(); - cam->set_projection(OrthoProjection(frust2d)); - GraphicsChannel *chan = w->get_channel(0); // root/full-window channel - nassertr(chan != (GraphicsChannel*)0L, NULL); - GraphicsLayer *layer = chan->make_layer(); - nassertr(layer != (GraphicsLayer*)0L, NULL); - DisplayRegion *dr = layer->make_display_region(); - nassertr(dr != (DisplayRegion*)0L, NULL); - dr->set_camera(cam); - if (gui_cat->is_debug()) - gui_cat->debug() << "2D layer created" << endl; + + if (root2d == (Node *)NULL) { + // If we weren't given a 2-d scene graph, then create one now. + // It lives in its own layer. + + Node* root2d_top = new NamedNode("GUI_top"); + root2d = new NamedNode("GUI"); + NodeRelation* root2d_arc = new RenderRelation(root2d_top, root2d); + root2d_arc->set_transition(new DepthTestTransition(DepthTestProperty::M_none), 1); + root2d_arc->set_transition(new DepthWriteTransition(DepthWriteTransition::off()), 1); + root2d_arc->set_transition(new LightTransition(LightTransition::all_off()), 1); + root2d_arc->set_transition(new MaterialTransition(MaterialTransition::off()), 1); + root2d_arc->set_transition(new CullFaceTransition(CullFaceProperty::M_cull_none), 1); + PT(Camera) cam = new Camera("GUI_cam"); + new RenderRelation(root2d, cam); + cam->set_scene(root2d_top); + Frustumf frust2d; + frust2d.make_ortho_2D(); + cam->set_projection(OrthoProjection(frust2d)); + GraphicsChannel *chan = w->get_channel(0); // root/full-window channel + nassertr(chan != (GraphicsChannel*)0L, NULL); + GraphicsLayer *layer = chan->make_layer(); + nassertr(layer != (GraphicsLayer*)0L, NULL); + DisplayRegion *dr = layer->make_display_region(); + nassertr(dr != (DisplayRegion*)0L, NULL); + dr->set_camera(cam); + if (gui_cat->is_debug()) + gui_cat->debug() << "2D layer created" << endl; + } + // now make the manager for this window ret = new GuiManager(watcher, root2d); if (gui_cat->is_debug()) diff --git a/panda/src/gui/guiManager.h b/panda/src/gui/guiManager.h index a5ead4a9c3..eabc8d2a42 100644 --- a/panda/src/gui/guiManager.h +++ b/panda/src/gui/guiManager.h @@ -32,7 +32,8 @@ private: INLINE GuiManager(MouseWatcher*, Node*); PUBLISHED: - static GuiManager* get_ptr(GraphicsWindow*, MouseAndKeyboard*); + static GuiManager* get_ptr(GraphicsWindow*, MouseAndKeyboard*, + Node *root2d = (Node *)NULL); void add_region(GuiRegion*); void add_label(GuiLabel*); diff --git a/panda/src/light/spotlight.cxx b/panda/src/light/spotlight.cxx index be52a245b0..71c581b463 100644 --- a/panda/src/light/spotlight.cxx +++ b/panda/src/light/spotlight.cxx @@ -76,7 +76,7 @@ write(ostream &out, int indent_level) const { //////////////////////////////////////////////////////////////////// float Spotlight::get_cutoff_angle(void) const { - const Projection* proj = get_projection(); + Projection* proj = ((ProjectionNode *)this)->get_projection(); Frustumf frustum; float cutoff = 0; if (proj->get_type() == PerspectiveProjection::get_class_type()) { diff --git a/panda/src/putil/updateSeq.I b/panda/src/putil/updateSeq.I index 532de47f97..a758006384 100644 --- a/panda/src/putil/updateSeq.I +++ b/panda/src/putil/updateSeq.I @@ -11,7 +11,7 @@ //////////////////////////////////////////////////////////////////// INLINE UpdateSeq:: UpdateSeq() { - _seq = (unsigned)SC_initial; + _seq = (unsigned int)SC_initial; } //////////////////////////////////////////////////////////////////// @@ -32,7 +32,19 @@ initial() { INLINE UpdateSeq UpdateSeq:: old() { UpdateSeq result; - result._seq = (unsigned)SC_old; + result._seq = (unsigned int)SC_old; + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: UpdateSeq::fresh (named constructor) +// Access: Public, Static +// Description: Returns an UpdateSeq in the 'fresh' state. +//////////////////////////////////////////////////////////////////// +INLINE UpdateSeq UpdateSeq:: +fresh() { + UpdateSeq result; + result._seq = (unsigned int)SC_fresh; return result; } @@ -64,7 +76,7 @@ operator = (const UpdateSeq ©) { //////////////////////////////////////////////////////////////////// INLINE void UpdateSeq:: clear() { - _seq = (unsigned)SC_initial; + _seq = (unsigned int)SC_initial; } //////////////////////////////////////////////////////////////////// @@ -75,7 +87,7 @@ clear() { //////////////////////////////////////////////////////////////////// INLINE bool UpdateSeq:: is_initial() const { - return _seq == SC_initial; + return _seq == (unsigned int)SC_initial; } //////////////////////////////////////////////////////////////////// @@ -85,18 +97,37 @@ is_initial() const { //////////////////////////////////////////////////////////////////// INLINE bool UpdateSeq:: is_old() const { - return _seq == SC_old; + return _seq == (unsigned int)SC_old; +} + +//////////////////////////////////////////////////////////////////// +// Function: UpdateSeq::is_fresh +// Access: Public +// Description: Returns true if the UpdateSeq is in the 'fresh' +// state. +//////////////////////////////////////////////////////////////////// +INLINE bool UpdateSeq:: +is_fresh() const { + return _seq == (unsigned int)SC_fresh; } //////////////////////////////////////////////////////////////////// // Function: UpdateSeq::is_special // Access: Public // Description: Returns true if the UpdateSeq is in any special -// states, i.e. 'initial' or 'old'. +// states, i.e. 'initial', 'old', or 'fresh'. //////////////////////////////////////////////////////////////////// INLINE bool UpdateSeq:: is_special() const { - return _seq <= (unsigned)SC_old; + switch (_seq) { + case (unsigned int)SC_initial: + case (unsigned int)SC_old: + case (unsigned int)SC_fresh: + return true; + + default: + return false; + } } //////////////////////////////////////////////////////////////////// @@ -127,10 +158,12 @@ operator != (const UpdateSeq &other) const { INLINE bool UpdateSeq:: operator < (const UpdateSeq &other) const { // The special cases of SC_initial or SC_old are less than all other - // non-special numbers, and SC_initial is less than SC_old. For all - // other cases, we use a circular comparision such that n < m iff - // (signed)(n - m) < 0. - return (is_special() || other.is_special()) ? (_seq < other._seq) : + // non-special numbers, and SC_initial is less than SC_old. The + // special case of SC_fresh is greater than all other non-special + // numbers. For all other cases, we use a circular comparision such + // that n < m iff (signed)(n - m) < 0. + return + (is_special() || other.is_special()) ? (_seq < other._seq) : ((signed int)(_seq - other._seq) < 0); } @@ -155,7 +188,7 @@ operator ++ () { if (is_special()) { // Oops, wraparound. We don't want to confuse the new value // with our special cases. - _seq = (unsigned)SC_old + 1; + _seq = (unsigned int)SC_old + 1; } return *this; @@ -189,6 +222,10 @@ output(ostream &out) const { out << "old"; break; + case SC_fresh: + out << "fresh"; + break; + default: out << _seq; } diff --git a/panda/src/putil/updateSeq.h b/panda/src/putil/updateSeq.h index b4020c6188..f9957dc5a4 100644 --- a/panda/src/putil/updateSeq.h +++ b/panda/src/putil/updateSeq.h @@ -22,15 +22,17 @@ // first created. This sequence is older than any other // sequence number. Secondly, a sequence number may be // explicitly set to 'old'. This is older than any -// other sequence number except 'initial'. All other -// sequences are numeric and are monotonically -// increasing. +// other sequence number except 'initial'. Finally, we +// have the explicit number 'fresh', which is newer +// than any other sequence number. All other sequences +// are numeric and are monotonically increasing. //////////////////////////////////////////////////////////////////// class EXPCL_PANDA UpdateSeq { public: INLINE UpdateSeq(); INLINE static UpdateSeq initial(); INLINE static UpdateSeq old(); + INLINE static UpdateSeq fresh(); INLINE UpdateSeq(const UpdateSeq ©); INLINE UpdateSeq &operator = (const UpdateSeq ©); @@ -39,6 +41,7 @@ public: INLINE bool is_initial() const; INLINE bool is_old() const; + INLINE bool is_fresh() const; INLINE bool is_special() const; INLINE bool operator == (const UpdateSeq &other) const; @@ -55,9 +58,10 @@ private: enum SpecialCases { SC_initial = 0, SC_old = 1, + SC_fresh = ~0, }; - unsigned _seq; + unsigned int _seq; }; INLINE ostream &operator << (ostream &out, const UpdateSeq &value); diff --git a/panda/src/ribgsg/ribGraphicsStateGuardian.cxx b/panda/src/ribgsg/ribGraphicsStateGuardian.cxx index 3fa042668b..5102ea785c 100644 --- a/panda/src/ribgsg/ribGraphicsStateGuardian.cxx +++ b/panda/src/ribgsg/ribGraphicsStateGuardian.cxx @@ -243,7 +243,7 @@ render_frame(const AllAttributesWrapper &initial_state) { // may be modified during rendering. //////////////////////////////////////////////////////////////////// void RIBGraphicsStateGuardian:: -render_scene(Node *root, const ProjectionNode *projnode, +render_scene(Node *root, ProjectionNode *projnode, const AllAttributesWrapper &initial_state) { _current_root_node = root; @@ -262,10 +262,10 @@ render_scene(Node *root, const ProjectionNode *projnode, //////////////////////////////////////////////////////////////////// void RIBGraphicsStateGuardian:: render_subgraph(RenderTraverser *traverser, - Node *subgraph, const ProjectionNode *projnode, + Node *subgraph, ProjectionNode *projnode, const AllAttributesWrapper &initial_state, const AllTransitionsWrapper &net_trans) { - const ProjectionNode *old_projection_node = _current_projection_node; + ProjectionNode *old_projection_node = _current_projection_node; _current_projection_node = projnode; (*_output) << "\n"; diff --git a/panda/src/ribgsg/ribGraphicsStateGuardian.h b/panda/src/ribgsg/ribGraphicsStateGuardian.h index 712d99e3a1..c87a2268df 100644 --- a/panda/src/ribgsg/ribGraphicsStateGuardian.h +++ b/panda/src/ribgsg/ribGraphicsStateGuardian.h @@ -40,10 +40,10 @@ public: virtual void prepare_display_region(); virtual void render_frame(const AllAttributesWrapper &initial_state); - virtual void render_scene(Node *root, const ProjectionNode *projnode, + virtual void render_scene(Node *root, ProjectionNode *projnode, const AllAttributesWrapper &initial_state); virtual void render_subgraph(RenderTraverser *traverser, - Node *subgraph, const ProjectionNode *projnode, + Node *subgraph, ProjectionNode *projnode, const AllAttributesWrapper &initial_state, const AllTransitionsWrapper &net_trans); virtual void render_subgraph(RenderTraverser *traverser, diff --git a/panda/src/sgattrib/billboardTransition.cxx b/panda/src/sgattrib/billboardTransition.cxx index c410325d28..fb0f994f1e 100644 --- a/panda/src/sgattrib/billboardTransition.cxx +++ b/panda/src/sgattrib/billboardTransition.cxx @@ -9,6 +9,7 @@ #include "renderRelation.h" #include +#include #include #include #include @@ -39,9 +40,9 @@ make_copy() const { //////////////////////////////////////////////////////////////////// bool BillboardTransition:: sub_render(NodeRelation *arc, const AllAttributesWrapper &, - AllTransitionsWrapper &trans, GraphicsStateGuardianBase *gsgbase) { + AllTransitionsWrapper &trans, RenderTraverser *trav) { Node *node = arc->get_child(); - GraphicsStateGuardian *gsg = DCAST(GraphicsStateGuardian, gsgbase); + GraphicsStateGuardian *gsg = trav->get_gsg(); // Get the current camera from the gsg const ProjectionNode *camera = gsg->get_current_projection_node(); @@ -50,7 +51,8 @@ sub_render(NodeRelation *arc, const AllAttributesWrapper &, // And the relative coordinate space. LMatrix4f rel_mat; NodeTransitionWrapper ntw(TransformTransition::get_class_type()); - wrt(camera, node, (&arc), (&arc) + 1, ntw, RenderRelation::get_class_type()); + wrt(camera, node, trav->begin(), trav->end(), + ntw, RenderRelation::get_class_type()); TransformTransition *tt; if (!get_transition_into(tt, ntw)) { // No relative transform. diff --git a/panda/src/sgattrib/billboardTransition.h b/panda/src/sgattrib/billboardTransition.h index e2a5f826db..b3fd322329 100644 --- a/panda/src/sgattrib/billboardTransition.h +++ b/panda/src/sgattrib/billboardTransition.h @@ -45,7 +45,7 @@ public: virtual bool sub_render(NodeRelation *arc, const AllAttributesWrapper &attrib, AllTransitionsWrapper &trans, - GraphicsStateGuardianBase *gsgbase); + RenderTraverser *trav); virtual bool has_sub_render() const; virtual void output(ostream &out) const; diff --git a/panda/src/sgattrib/drawBoundsTransition.cxx b/panda/src/sgattrib/drawBoundsTransition.cxx index a3f1ad1233..d6527448ad 100644 --- a/panda/src/sgattrib/drawBoundsTransition.cxx +++ b/panda/src/sgattrib/drawBoundsTransition.cxx @@ -20,6 +20,7 @@ #include #include #include +#include #include TypeHandle DrawBoundsTransition::_type_handle; @@ -70,8 +71,8 @@ make_copy() const { //////////////////////////////////////////////////////////////////// bool DrawBoundsTransition:: sub_render(NodeRelation *arc, const AllAttributesWrapper &attrib, - AllTransitionsWrapper &, GraphicsStateGuardianBase *gsgbase) { - GraphicsStateGuardian *gsg = DCAST(GraphicsStateGuardian, gsgbase); + AllTransitionsWrapper &, RenderTraverser *trav) { + GraphicsStateGuardian *gsg = trav->get_gsg(); const BoundingVolume &vol = arc->get_bound(); if (!vol.is_empty() && !vol.is_infinite()) { diff --git a/panda/src/sgattrib/drawBoundsTransition.h b/panda/src/sgattrib/drawBoundsTransition.h index 3e5d1c4217..c0f2efecf4 100644 --- a/panda/src/sgattrib/drawBoundsTransition.h +++ b/panda/src/sgattrib/drawBoundsTransition.h @@ -29,7 +29,7 @@ public: virtual bool sub_render(NodeRelation *arc, const AllAttributesWrapper &attrib, AllTransitionsWrapper &trans, - GraphicsStateGuardianBase *gsgbase); + RenderTraverser *trav); virtual bool has_sub_render() const; NodeAttributes _outside_attrib; diff --git a/panda/src/sgattrib/pruneTransition.cxx b/panda/src/sgattrib/pruneTransition.cxx index ce0edfca25..9eb83d8a45 100644 --- a/panda/src/sgattrib/pruneTransition.cxx +++ b/panda/src/sgattrib/pruneTransition.cxx @@ -29,7 +29,7 @@ make_copy() const { //////////////////////////////////////////////////////////////////// bool PruneTransition:: sub_render(NodeRelation *, const AllAttributesWrapper &, - AllTransitionsWrapper &, GraphicsStateGuardianBase *) { + AllTransitionsWrapper &, RenderTraverser *) { return false; } diff --git a/panda/src/sgattrib/pruneTransition.h b/panda/src/sgattrib/pruneTransition.h index 4be80b190c..aa5748b0e1 100644 --- a/panda/src/sgattrib/pruneTransition.h +++ b/panda/src/sgattrib/pruneTransition.h @@ -29,7 +29,7 @@ public: virtual bool sub_render(NodeRelation *arc, const AllAttributesWrapper &attrib, AllTransitionsWrapper &trans, - GraphicsStateGuardianBase *gsgbase); + RenderTraverser *trav); virtual bool has_sub_render() const; public: diff --git a/panda/src/sgraph/projectionNode.cxx b/panda/src/sgraph/projectionNode.cxx index e839690bbd..3e56652db8 100644 --- a/panda/src/sgraph/projectionNode.cxx +++ b/panda/src/sgraph/projectionNode.cxx @@ -30,26 +30,43 @@ make_copy() const { //////////////////////////////////////////////////////////////////// // Function: set_projection -// Access: -// Description: +// Access: Public +// Description: Sets up the ProjectionNode using a copy of the +// indicated Projection. If the original Projection is +// changed or destroyed, this ProjectionNode is not +// affected. //////////////////////////////////////////////////////////////////// -void ProjectionNode::set_projection( const Projection& projection ) -{ - _projection = projection.make_copy(); +void ProjectionNode:: +set_projection(const Projection &projection) { + _projection = projection.make_copy(); +} + +//////////////////////////////////////////////////////////////////// +// Function: share_projection +// Access: Public +// Description: This is similar to set_projection(), but the +// Projection is assigned by pointer. If the original +// Projection is changed, this ProjectionNode is +// immediately affected. +//////////////////////////////////////////////////////////////////// +void ProjectionNode:: +share_projection(Projection *projection) { + _projection = projection; } //////////////////////////////////////////////////////////////////// // Function: get_projection -// Access: -// Description: +// Access: Public +// Description: Returns a pointer to particular Projection associated +// with this ProjectionNode. //////////////////////////////////////////////////////////////////// -const Projection* ProjectionNode::get_projection( void ) const -{ - if (_projection == NULL) { - // If we have no projection yet, just return a default projection. +Projection *ProjectionNode:: +get_projection() { + if (_projection == (Projection *)NULL) { + // If we have no projection yet, give us a default Projection. Frustumf f; - static PerspectiveProjection default_projection(f); - return &default_projection; + _projection = new PerspectiveProjection(f); } + return _projection; } diff --git a/panda/src/sgraph/projectionNode.h b/panda/src/sgraph/projectionNode.h index 1a35c4828d..3b8252397f 100644 --- a/panda/src/sgraph/projectionNode.h +++ b/panda/src/sgraph/projectionNode.h @@ -24,7 +24,7 @@ //////////////////////////////////////////////////////////////////// class EXPCL_PANDA ProjectionNode : public NamedNode { PUBLISHED: - INLINE ProjectionNode(const string& name = ""); + INLINE ProjectionNode(const string &name = ""); public: INLINE ProjectionNode(const ProjectionNode ©); @@ -33,12 +33,12 @@ public: virtual Node *make_copy() const; PUBLISHED: - void set_projection( const Projection& projection ); - const Projection* get_projection( void ) const; + void set_projection(const Projection &projection); + void share_projection(Projection *projection); + Projection *get_projection(); protected: - - PT(Projection) _projection; + PT(Projection) _projection; public: diff --git a/panda/src/sgraph/renderTraverser.I b/panda/src/sgraph/renderTraverser.I index 588ac6feb6..1e6ca4a843 100644 --- a/panda/src/sgraph/renderTraverser.I +++ b/panda/src/sgraph/renderTraverser.I @@ -7,13 +7,76 @@ //////////////////////////////////////////////////////////////////// // Function: RenderTraverser::Constructor // Access: Public +// Description: Creates a new RenderTraverser ready to traverse a +// scene graph beginning at the end of the arc chain +// indicated in arc_chain (either an empty ArcChain, or +// the result of get_arc_chain() from some other +// traverser), with the indicated graph_type (usually +// RenderRelation) and for the indicated gsg. +//////////////////////////////////////////////////////////////////// +INLINE RenderTraverser:: +RenderTraverser(GraphicsStateGuardian *gsg, TypeHandle graph_type, + const ArcChain &arc_chain) : + _gsg(gsg), + _graph_type(graph_type), + _arc_chain(arc_chain) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: RenderTraverser::Destructor +// Access: Public // Description: //////////////////////////////////////////////////////////////////// INLINE RenderTraverser:: -RenderTraverser(GraphicsStateGuardian *gsg, TypeHandle graph_type) : - _gsg(gsg), - _graph_type(graph_type) -{ +~RenderTraverser() { +} + +//////////////////////////////////////////////////////////////////// +// Function: RenderTraverser::get_arc_chain +// Access: Public +// Description: Returns the complete chain of arcs from the root to +// the current node in the traversal. +//////////////////////////////////////////////////////////////////// +INLINE const ArcChain &RenderTraverser:: +get_arc_chain() const { + return _arc_chain; +} + +//////////////////////////////////////////////////////////////////// +// Function: RenderTraverser::begin +// Access: Public +// Description: Returns an iterator that can be used to traverse the +// list of arcs from the root to the current node in the +// traversal. +//////////////////////////////////////////////////////////////////// +INLINE RenderTraverser::const_iterator RenderTraverser:: +begin() const { + return _arc_chain.begin(); +} + +//////////////////////////////////////////////////////////////////// +// Function: RenderTraverser::end +// Access: Public +// Description: Returns an iterator that can be used to traverse the +// list of arcs from the root to the current node in the +// traversal. +//////////////////////////////////////////////////////////////////// +INLINE RenderTraverser::const_iterator RenderTraverser:: +end() const { + return _arc_chain.end(); +} + +//////////////////////////////////////////////////////////////////// +// Function: RenderTraverser::empty +// Access: Public +// Description: Returns true if the list of arcs returned by begin() +// .. end() is empty (i.e. begin() == end()), false +// otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool RenderTraverser:: +empty() const { + return _arc_chain.empty(); } //////////////////////////////////////////////////////////////////// @@ -35,3 +98,29 @@ INLINE TypeHandle RenderTraverser:: get_graph_type() const { return _graph_type; } + +//////////////////////////////////////////////////////////////////// +// Function: RenderTraverser::mark_forward_arc +// Access: Public +// Description: To be called by the derived class's forward_arc() +// method, this updates the list of arcs traversed to +// include the current arc. +//////////////////////////////////////////////////////////////////// +INLINE void RenderTraverser:: +mark_forward_arc(NodeRelation *arc) { + _arc_chain.push_back(arc); +} + +//////////////////////////////////////////////////////////////////// +// Function: RenderTraverser::mark_backward_arc +// Access: Public +// Description: To be called by the derived class's forward_arc() +// method, this updates the list of arcs traversed to +// remove the current arc. +//////////////////////////////////////////////////////////////////// +INLINE void RenderTraverser:: +mark_backward_arc(NodeRelation *arc) { + nassertv(!_arc_chain.empty()); + nassertv(_arc_chain.back() == arc); + _arc_chain.pop_back(); +} diff --git a/panda/src/sgraph/renderTraverser.h b/panda/src/sgraph/renderTraverser.h index 9eb29fbb92..08978c58cd 100644 --- a/panda/src/sgraph/renderTraverser.h +++ b/panda/src/sgraph/renderTraverser.h @@ -8,11 +8,14 @@ #include +#include #include #include +#include class GraphicsStateGuardian; class Node; +class NodeRelation; class AllAttributesWrapper; class AllTransitionsWrapper; @@ -26,7 +29,18 @@ class AllTransitionsWrapper; //////////////////////////////////////////////////////////////////// class EXPCL_PANDA RenderTraverser : public TypedReferenceCount { public: - INLINE RenderTraverser(GraphicsStateGuardian *gsg, TypeHandle graph_type); + INLINE RenderTraverser(GraphicsStateGuardian *gsg, + TypeHandle graph_type, + const ArcChain &arc_chain); + INLINE ~RenderTraverser(); + + typedef ArcChain::iterator iterator; + typedef ArcChain::const_iterator const_iterator; + + INLINE const ArcChain &get_arc_chain() const; + INLINE const_iterator begin() const; + INLINE const_iterator end() const; + INLINE bool empty() const; PUBLISHED: INLINE GraphicsStateGuardian *get_gsg() const; @@ -41,9 +55,16 @@ PUBLISHED: virtual void output(ostream &out) const; virtual void write(ostream &out, int indent_level = 0) const; +protected: + // These methods are to be called by derived classes as we traverse + // each arc. They update the arc list returned by begin()/end(). + INLINE void mark_forward_arc(NodeRelation *arc); + INLINE void mark_backward_arc(NodeRelation *arc); + protected: GraphicsStateGuardian *_gsg; TypeHandle _graph_type; + ArcChain _arc_chain; public: static TypeHandle get_class_type() { diff --git a/panda/src/sgraphutil/directRenderTraverser.cxx b/panda/src/sgraphutil/directRenderTraverser.cxx index 792f743cc6..c8ec6f5a1b 100644 --- a/panda/src/sgraphutil/directRenderTraverser.cxx +++ b/panda/src/sgraphutil/directRenderTraverser.cxx @@ -7,6 +7,7 @@ #include "config_sgraphutil.h" #include "frustumCullTraverser.h" +#include #include #include #include @@ -18,6 +19,8 @@ #include #include #include +#include +#include #include #include #include @@ -32,8 +35,9 @@ PStatCollector DirectRenderTraverser::_draw_pcollector = // Description: //////////////////////////////////////////////////////////////////// DirectRenderTraverser:: -DirectRenderTraverser(GraphicsStateGuardian *gsg, TypeHandle graph_type) : - RenderTraverser(gsg, graph_type) +DirectRenderTraverser(GraphicsStateGuardian *gsg, TypeHandle graph_type, + const ArcChain &arc_chain) : + RenderTraverser(gsg, graph_type, arc_chain) { } @@ -72,7 +76,22 @@ traverse(Node *root, level_state._decal_mode = decal_attrib->is_on(); } - fc_traverse(root, *this, render_state, level_state, + // Determine the relative transform matrix from the camera to our + // starting node. This is important for proper view-frustum + // culling. + LMatrix4f rel_from_camera; + NodeTransitionWrapper ntw(TransformTransition::get_class_type()); + wrt(_gsg->get_current_projection_node(), root, begin(), end(), + ntw, get_graph_type()); + const TransformTransition *tt; + if (get_transition_into(tt, ntw)) { + rel_from_camera = tt->get_matrix(); + } else { + // No relative transform. + rel_from_camera = LMatrix4f::ident_mat(); + } + + fc_traverse(root, rel_from_camera, *this, render_state, level_state, _gsg, _graph_type); if (level_state._decal_mode && @@ -100,7 +119,7 @@ reached_node(Node *node, AllAttributesWrapper &render_state, AllTransitionsWrapper new_trans; - if (!node->sub_render(render_state, new_trans, _gsg)) { + if (!node->sub_render(render_state, new_trans, this)) { return false; } render_state.apply_in_place(new_trans); @@ -146,16 +165,22 @@ forward_arc(NodeRelation *arc, AllTransitionsWrapper &trans, // return true. For Shader types, this will fire off another render // and return false. + mark_forward_arc(arc); + AllTransitionsWrapper::const_iterator nti; for (nti = trans.begin(); nti != trans.end(); ++nti) { NodeTransition *t = (*nti).second.get_trans(); AllTransitionsWrapper new_trans; - if (!t->sub_render(arc, post, new_trans, _gsg)) { + if (!t->sub_render(arc, post, new_trans, this)) { carry_on = false; } post.apply_in_place(new_trans); } + if (!carry_on) { + mark_backward_arc(arc); + } + return carry_on; } @@ -169,6 +194,7 @@ void DirectRenderTraverser:: backward_arc(NodeRelation *arc, AllTransitionsWrapper &, AllAttributesWrapper &, AllAttributesWrapper &post, const DirectRenderLevelState &level_state) { + mark_backward_arc(arc); if (level_state._decal_mode) { // Reset the state to redraw the base geometry. _gsg->set_state(post.get_attributes(), true); diff --git a/panda/src/sgraphutil/directRenderTraverser.h b/panda/src/sgraphutil/directRenderTraverser.h index 155d2d8aae..a0536488e2 100644 --- a/panda/src/sgraphutil/directRenderTraverser.h +++ b/panda/src/sgraphutil/directRenderTraverser.h @@ -36,7 +36,8 @@ class EXPCL_PANDA DirectRenderTraverser : public RenderTraverser, public TraverserVisitor { public: - DirectRenderTraverser(GraphicsStateGuardian *gsg, TypeHandle graph_type); + DirectRenderTraverser(GraphicsStateGuardian *gsg, TypeHandle graph_type, + const ArcChain &arc_chain = ArcChain()); virtual ~DirectRenderTraverser(); virtual void traverse(Node *root, diff --git a/panda/src/sgraphutil/frustumCullTraverser.I b/panda/src/sgraphutil/frustumCullTraverser.I index de3c681b51..3a21405edd 100644 --- a/panda/src/sgraphutil/frustumCullTraverser.I +++ b/panda/src/sgraphutil/frustumCullTraverser.I @@ -4,11 +4,11 @@ //////////////////////////////////////////////////////////////////// #include "frustumCullTraverser.h" -#include "get_rel_pos.h" #include "config_sgraphutil.h" #include #include +#include #include //////////////////////////////////////////////////////////////////// @@ -18,7 +18,7 @@ //////////////////////////////////////////////////////////////////// template FrustumCullTraverser:: -FrustumCullTraverser(Node *root, +FrustumCullTraverser(Node *root, const LMatrix4f &rel_from_camera, Visitor &visitor, const AttributeWrapper &initial_render_state, const LevelState &initial_level_state, @@ -36,7 +36,7 @@ FrustumCullTraverser(Node *root, // If we're to be performing view-frustum culling, determine the // bounding volume associated with the current viewing frustum. - const ProjectionNode *camera = _gsg->get_current_projection_node(); + ProjectionNode *camera = _gsg->get_current_projection_node(); if (camera != (const ProjectionNode *)NULL) { const Projection *proj = camera->get_projection(); nassertv(proj != (const Projection *)NULL); @@ -49,17 +49,14 @@ FrustumCullTraverser(Node *root, } } - LMatrix4f mat; - get_rel_mat(_gsg->get_current_projection_node(), root, mat); - local_frustum = DCAST(GeometricBoundingVolume, _view_frustum->make_copy()); - local_frustum->xform(mat); + local_frustum->xform(rel_from_camera); if (sgraphutil_cat.is_spam()) { sgraphutil_cat.spam() << "Beginning frustum cull, frustum is: " << *local_frustum << "\n" << "Transform is:\n"; - mat.write(sgraphutil_cat.spam(false), 2); + rel_from_camera.write(sgraphutil_cat.spam(false), 2); } } diff --git a/panda/src/sgraphutil/frustumCullTraverser.h b/panda/src/sgraphutil/frustumCullTraverser.h index 1ee75e5157..b6777b645b 100644 --- a/panda/src/sgraphutil/frustumCullTraverser.h +++ b/panda/src/sgraphutil/frustumCullTraverser.h @@ -28,7 +28,7 @@ public: typedef TYPENAME Visitor::TransitionWrapper TransitionWrapper; typedef TYPENAME Visitor::AttributeWrapper AttributeWrapper; - FrustumCullTraverser(Node *root, + FrustumCullTraverser(Node *root, const LMatrix4f &rel_from_camera, Visitor &visitor, const AttributeWrapper &initial_render_state, const LevelState &initial_level_state, @@ -67,12 +67,12 @@ protected: // Convenience function. template INLINE void -fc_traverse(Node *root, Visitor &visitor, +fc_traverse(Node *root, const LMatrix4f &rel_from_camera, Visitor &visitor, const AttributeWrapper &initial_render_state, const LevelState &initial_level_state, GraphicsStateGuardian *gsg, TypeHandle graph_type) { FrustumCullTraverser - fct(root, visitor, initial_render_state, + fct(root, rel_from_camera, visitor, initial_render_state, initial_level_state, gsg, graph_type); } diff --git a/panda/src/shader/shaderTransition.cxx b/panda/src/shader/shaderTransition.cxx index 93ef242bd2..fb050ce746 100644 --- a/panda/src/shader/shaderTransition.cxx +++ b/panda/src/shader/shaderTransition.cxx @@ -245,9 +245,9 @@ must_blend() //////////////////////////////////////////////////////////////////// bool ShaderTransition:: sub_render(NodeRelation *arc, const AllAttributesWrapper &attrib, - AllTransitionsWrapper &trans, GraphicsStateGuardianBase *gsgbase) { + AllTransitionsWrapper &trans, RenderTraverser *trav) { Node *node = arc->get_child(); - GraphicsStateGuardian *gsg = DCAST(GraphicsStateGuardian, gsgbase); + GraphicsStateGuardian *gsg = trav->get_gsg(); bool multipass_on = false; // No shaders; never mind. diff --git a/panda/src/shader/shaderTransition.h b/panda/src/shader/shaderTransition.h index a333052bcc..f3286dc73f 100644 --- a/panda/src/shader/shaderTransition.h +++ b/panda/src/shader/shaderTransition.h @@ -70,7 +70,7 @@ public: virtual bool sub_render(NodeRelation *arc, const AllAttributesWrapper &attrib, AllTransitionsWrapper &trans, - GraphicsStateGuardianBase *gsgbase); + RenderTraverser *trav); virtual bool has_sub_render() const; private: diff --git a/panda/src/switchnode/LODNode.cxx b/panda/src/switchnode/LODNode.cxx index b13200c8d5..e0711e09cc 100644 --- a/panda/src/switchnode/LODNode.cxx +++ b/panda/src/switchnode/LODNode.cxx @@ -12,12 +12,12 @@ #include #include -#include #include #include #include #include #include +#include //////////////////////////////////////////////////////////////////// // Static variables @@ -69,9 +69,9 @@ output(ostream &out) const { //////////////////////////////////////////////////////////////////// bool LODNode:: sub_render(const AllAttributesWrapper &attrib, AllTransitionsWrapper &trans, - GraphicsStateGuardianBase *gsgbase) { + RenderTraverser *trav) { - GraphicsStateGuardian *gsg = DCAST(GraphicsStateGuardian, gsgbase); + GraphicsStateGuardian *gsg = trav->get_gsg(); // Get the current camera position from the gsg const ProjectionNode* camera = gsg->get_current_projection_node(); @@ -81,7 +81,8 @@ sub_render(const AllAttributesWrapper &attrib, AllTransitionsWrapper &trans, LPoint3f LOD_pos; NodeTransitionWrapper ntw(TransformTransition::get_class_type()); - wrt(this, camera, ntw, RenderRelation::get_class_type()); + wrt(this, camera, trav->begin(), trav->end(), + ntw, RenderRelation::get_class_type()); const TransformTransition *tt; if (get_transition_into(tt, ntw)) { LOD_pos = _lod._center * tt->get_matrix(); @@ -110,8 +111,7 @@ sub_render(const AllAttributesWrapper &attrib, AllTransitionsWrapper &trans, new_trans.compose_in_place(arc_trans); // Now render everything from this node and below. - gsg->render_subgraph(gsg->get_render_traverser(), - arc->get_child(), attrib, new_trans); + gsg->render_subgraph(trav, arc->get_child(), attrib, new_trans); } else { if (switchnode_cat.is_debug()) { diff --git a/panda/src/switchnode/LODNode.h b/panda/src/switchnode/LODNode.h index 64101d3fdc..e981675892 100644 --- a/panda/src/switchnode/LODNode.h +++ b/panda/src/switchnode/LODNode.h @@ -51,7 +51,7 @@ public: virtual bool sub_render(const AllAttributesWrapper &attrib, AllTransitionsWrapper &trans, - GraphicsStateGuardianBase *gsgbase); + RenderTraverser *trav); virtual bool has_sub_render() const; public: diff --git a/panda/src/switchnode/sequenceNode.cxx b/panda/src/switchnode/sequenceNode.cxx index 844fa228ca..685a445caf 100644 --- a/panda/src/switchnode/sequenceNode.cxx +++ b/panda/src/switchnode/sequenceNode.cxx @@ -16,6 +16,7 @@ #include #include #include +#include //////////////////////////////////////////////////////////////////// // Static variables @@ -62,9 +63,8 @@ set_switch_time(float switch_time) //////////////////////////////////////////////////////////////////// bool SequenceNode:: sub_render(const AllAttributesWrapper &attrib, AllTransitionsWrapper &trans, - GraphicsStateGuardianBase *gsgbase) -{ - GraphicsStateGuardian *gsg = DCAST(GraphicsStateGuardian, gsgbase); + RenderTraverser *trav) { + GraphicsStateGuardian *gsg = trav->get_gsg(); // Determine which child to traverse int num_children = get_num_children(RenderRelation::get_class_type()); @@ -88,8 +88,7 @@ sub_render(const AllAttributesWrapper &attrib, AllTransitionsWrapper &trans, new_trans.compose_in_place(arc_trans); // Now render everything from this node and below. - gsg->render_subgraph(gsg->get_render_traverser(), - arc->get_child(), attrib, new_trans); + gsg->render_subgraph(trav, arc->get_child(), attrib, new_trans); } else { if (switchnode_cat.is_debug()) { diff --git a/panda/src/switchnode/sequenceNode.h b/panda/src/switchnode/sequenceNode.h index beba85c939..65a8e90cee 100644 --- a/panda/src/switchnode/sequenceNode.h +++ b/panda/src/switchnode/sequenceNode.h @@ -32,7 +32,7 @@ PUBLISHED: public: virtual bool sub_render(const AllAttributesWrapper &attrib, AllTransitionsWrapper &trans, - GraphicsStateGuardianBase *gsgbase); + RenderTraverser *trav); virtual bool has_sub_render() const; public: diff --git a/panda/src/testbed/Sources.pp b/panda/src/testbed/Sources.pp index 8b6d24e6f4..7977426200 100644 --- a/panda/src/testbed/Sources.pp +++ b/panda/src/testbed/Sources.pp @@ -17,6 +17,7 @@ #begin test_bin_target #define TARGET chat + #define LOCAL_LIBS $[LOCAL_LIBS] chat #define SOURCES \ chat_test.cxx diff --git a/panda/src/testbed/chat_test.cxx b/panda/src/testbed/chat_test.cxx index 6206c3e32d..34ef48a9ec 100644 --- a/panda/src/testbed/chat_test.cxx +++ b/panda/src/testbed/chat_test.cxx @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include @@ -50,22 +49,23 @@ void chat_keys(EventHandler& eh) { eh.add_hook("chat_exit", event_chat_exit); eh.add_hook("chat_overflow", event_chat_overflow); - PT_NamedNode font = loader.load_sync("ttf-comic"); + PT_Node font = loader.load_sync("ttf-comic"); // Create the input text node input_text_node = new TextNode("input_text_node"); input_text_node->set_billboard(false); input_text_node->set_font(font.p()); input_text_node->set_text("Press Enter to begin chat mode."); + input_text_node->set_wordwrap(12.0); RenderRelation *text_arc = new RenderRelation(cameras, input_text_node); LMatrix4f mat = LMatrix4f::scale_mat(0.25); - mat.set_row(3, LVector3f(-3, 8, -2.4)); + mat.set_row(3, LVector3f(-3, 8, -1.4)); text_arc->set_transition(new TransformTransition(mat)); LightTransition *no_light = new LightTransition(LightTransition::all_off()); text_arc->set_transition(no_light); chat_input = new ChatInput(input_text_node, "chat input"); - chat_input->set_max_chars(20); + chat_input->set_max_lines(2); // Create the output text node output_text_node = new TextNode("output_text_node"); diff --git a/panda/src/testbed/demo.cxx b/panda/src/testbed/demo.cxx index ff67a5e1d6..38a2614065 100644 --- a/panda/src/testbed/demo.cxx +++ b/panda/src/testbed/demo.cxx @@ -78,6 +78,7 @@ RenderRelation *flare_arc = (RenderRelation *)NULL; DownRelationPointers *current_siblings; DownRelationPointers::iterator current_sib; +/* void setup_panda2d() { static bool already_setup = false; @@ -173,7 +174,6 @@ setup_panda2d() { } else { nout << "Couldn't find lilsmiley.egg\n"; } - } static void @@ -191,6 +191,7 @@ event_out_label2d(CPT_Event) { label2d->set_card_color(0.5, 0.5, 0.5, 0.5); } +*/ static void @@ -220,6 +221,9 @@ set_highlight(Node *node) { const BoundingVolume &vol = arc->get_bound(); nout << "Bounding volume of arc is " << vol << "\n"; + nout << "Transitions on arc:\n"; + arc->write_transitions(nout, 2); + arc->set_transition(new DrawBoundsTransition); bounds_arc = arc; } @@ -408,15 +412,6 @@ event_h(CPT_Event) { } } -static void -event_2(CPT_Event) { - static bool is_setup = false; - if (!is_setup) { - setup_panda2d(); - is_setup = true; - } -} - static void attach_sky() { // Load the sun and sky sky = DCAST(NamedNode, loader.load_sync("sky")); @@ -556,8 +551,10 @@ void demo_keys(EventHandler&) { new RenderRelation( lights, dlight ); have_dlight = true; + /* event_handler.add_hook("mw-in-label2d", event_in_label2d); event_handler.add_hook("mw-out-label2d", event_out_label2d); + */ event_handler.add_hook("h", event_h); event_handler.add_hook("up", event_up); @@ -574,8 +571,6 @@ void demo_keys(EventHandler&) { event_handler.add_hook("f8", event_fkey); event_handler.add_hook("f9", event_fkey); - event_handler.add_hook("2", event_2); - event_handler.add_hook("L", event_L); event_handler.add_hook("k", event_k); event_handler.add_hook("a", event_a);