*** empty log message ***

This commit is contained in:
David Rose 2001-01-09 03:07:29 +00:00
parent 7a110a31cd
commit faa13d10e5
81 changed files with 1322 additions and 373 deletions

View File

@ -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;

View File

@ -17,16 +17,11 @@
#include <nodePath.h>
#include <dconfig.h>
#define testint 1
#define testfloat 1.2345
#define testcstring "testcstring"
#include <string>
#define teststring string("teststring")
ConfigureDecl(config_showbase, EXPCL_DIRECT, EXPTP_DIRECT);
typedef Config::Config<ConfigureGetConfig_config_showbase> 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();

View File

@ -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));
}

View File

@ -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)) {

View File

@ -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();

View File

@ -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);

View File

@ -11,4 +11,6 @@
NotifyCategoryDecl(cull, EXPCL_PANDA, EXPTP_PANDA);
extern const bool cull_force_update;
#endif

View File

@ -10,6 +10,8 @@
#include "cullStateLookup.h"
#include <updateSeq.h>
////////////////////////////////////////////////////////////////////
// Class : CullLevelState
// Description : This is the state information the
@ -19,6 +21,7 @@
class EXPCL_PANDA CullLevelState {
public:
CullStateLookup *_lookup;
UpdateSeq _now;
};
#endif

View File

@ -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;
}

View File

@ -4,6 +4,7 @@
////////////////////////////////////////////////////////////////////
#include "cullState.h"
#include "config_cull.h"
#include <indent.h>
#include <graphicsStateGuardian.h>
@ -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 << ")";

View File

@ -8,6 +8,8 @@
#include <pandabase.h>
#include "config_cull.h"
#include <geomNode.h>
#include <allTransitionsWrapper.h>
#include <allAttributesWrapper.h>
@ -15,10 +17,10 @@
#include <pointerToArray.h>
#include <updateSeq.h>
#include <referenceCount.h>
#include <pt_Node.h>
#include <vector_PT_Node.h>
#include <arcChain.h>
#include <map>
#include <vector>
class GraphicsStateGuardian;
class GeomBin;
@ -34,8 +36,8 @@ class GeomBin;
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA CullState : public ReferenceCount {
public:
typedef vector<PT(GeomNode)> CurrentGeomNodes;
typedef vector_PT_Node CurrentDirectNodes;
typedef vector<ArcChain> CurrentGeomNodes;
typedef vector<ArcChain> 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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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<States::iterator, bool> 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);
}

View File

@ -14,9 +14,10 @@
#include <wrt.h>
#include <frustumCullTraverser.h>
#include <graphicsStateGuardian.h>
#include <billboardTransition.h>
#include <decalTransition.h>
#include <pruneTransition.h>
#include <transformTransition.h>
#include <nodeTransitionWrapper.h>
#include <indent.h>
#include <config_sgraphutil.h> // for implicit_app_traversal
#include <pStatTimer.h>
@ -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;
}

View File

@ -37,7 +37,8 @@ class EXPCL_PANDA CullTraverser :
public RenderTraverser,
public TraverserVisitor<NullTransitionWrapper, CullLevelState> {
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<PT(GeomBin)> Bins;
@ -96,6 +103,7 @@ private:
CullStateLookup _lookup;
int _nested_count;
UpdateSeq _now;
public:
// Statistics

View File

@ -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 &copy) :
_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 &copy) {
_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()));
}
}

View File

@ -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));
}
}

View File

@ -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 &copy);
INLINE void operator = (const NodeEntry &copy);
@ -51,7 +51,7 @@ private:
private:
float _distance;
PT(CullState) _state;
Node *_node;
ArcChain _arc_chain;
bool _is_direct;
};

View File

@ -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 &copy) :
_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 &copy) {
_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()));
}
}

View File

@ -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));
}
}

View File

@ -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 &copy);
INLINE void operator = (const NodeEntry &copy);
@ -48,7 +48,7 @@ private:
private:
int _draw_order;
PT(CullState) _state;
Node *_node;
ArcChain _arc_chain;
bool _is_direct;
};

View File

@ -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());
}
}
}

View File

@ -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;
}

View File

@ -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()

View File

@ -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;

View File

@ -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,

View File

@ -14,6 +14,7 @@
#include <billboardTransition.h>
#include <transformAttribute.h>
#include <transparencyTransition.h>
#include <renderTraverser.h>
#include <orthoProjection.h>
#include <perspectiveProjection.h>
@ -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);

View File

@ -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:

View File

@ -50,9 +50,12 @@ template<class T>
void PointerToBase<T>::
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);
}
}
}

View File

@ -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<class RefCountType>
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;
}
}

View File

@ -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

View File

@ -19,6 +19,7 @@
#include "typeHandle.h"
#include "memoryUsage.h"
#include "config_express.h"
#include <stdlib.h>
@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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 \

219
panda/src/graph/arcChain.I Normal file
View File

@ -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 &copy) :
_head(copy._head)
{
}
////////////////////////////////////////////////////////////////////
// Function: ArcChain::Copy Assignment Operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void ArcChain::
operator = (const ArcChain &copy) {
_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);
}
}

View File

@ -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();
}
}

105
panda/src/graph/arcChain.h Normal file
View File

@ -0,0 +1,105 @@
// Filename: arcChain.h
// Created by: drose (05Jan01)
//
////////////////////////////////////////////////////////////////////
#ifndef ARCCHAIN_H
#define ARCCHAIN_H
#include <pandabase.h>
#include "nodeRelation.h"
#include <pointerTo.h>
#include <referenceCount.h>
#include <notify.h>
////////////////////////////////////////////////////////////////////
// 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 &copy);
INLINE void operator = (const ArcChain &copy);
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

View File

@ -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

View File

@ -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;

View File

@ -176,8 +176,17 @@ internal_compare_to(const NodeTransition *other) const {
const MatrixTransition<Matrix> *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;
}
////////////////////////////////////////////////////////////////////

View File

@ -232,7 +232,7 @@ get_child(TypeHandle type, int index) const {
////////////////////////////////////////////////////////////////////
bool Node::
sub_render(const AllAttributesWrapper &, AllTransitionsWrapper &,
GraphicsStateGuardianBase *) {
RenderTraverser *) {
return true;
}

View File

@ -15,7 +15,7 @@
#include <luse.h>
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:

View File

@ -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

View File

@ -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()];
}
////////////////////////////////////////////////////////////////////

View File

@ -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);

View File

@ -36,7 +36,7 @@ get_handle() const {
////////////////////////////////////////////////////////////////////
bool NodeTransition::
sub_render(NodeRelation *, const AllAttributesWrapper &,
AllTransitionsWrapper &, GraphicsStateGuardianBase *) {
AllTransitionsWrapper &, RenderTraverser *) {
return true;
}

View File

@ -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;

View File

@ -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<class TransitionWrapper>
@ -417,6 +455,7 @@ wrt(const Node *from,
result, graph_type);
}
#ifndef NDEBUG
template<class TransitionWrapper>
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<class TransitionWrapper>
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<class TransitionWrapper>
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<class TransitionWrapper>
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<class TransitionWrapper>
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);
}

View File

@ -8,6 +8,10 @@
#include <pandabase.h>
#include "nodeRelation.h"
#include "node.h"
#include "config_graph.h"
#include <typeHandle.h>
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<class TransitionWrapper>
Node *
INLINE Node *
wrt_subtree(NodeRelation *arc, Node *to, TransitionWrapper &result,
TypeHandle graph_type);

View File

@ -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())

View File

@ -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*);

View File

@ -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()) {

View File

@ -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 &copy) {
////////////////////////////////////////////////////////////////////
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;
}

View File

@ -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 &copy);
INLINE UpdateSeq &operator = (const UpdateSeq &copy);
@ -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);

View File

@ -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";

View File

@ -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,

View File

@ -9,6 +9,7 @@
#include "renderRelation.h"
#include <graphicsStateGuardian.h>
#include <renderTraverser.h>
#include <projectionNode.h>
#include <look_at.h>
#include <nodeTransitionWrapper.h>
@ -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.

View File

@ -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;

View File

@ -20,6 +20,7 @@
#include <allTransitionsWrapper.h>
#include <allAttributesWrapper.h>
#include <graphicsStateGuardian.h>
#include <renderTraverser.h>
#include <geomSphere.h>
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()) {

View File

@ -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;

View File

@ -29,7 +29,7 @@ make_copy() const {
////////////////////////////////////////////////////////////////////
bool PruneTransition::
sub_render(NodeRelation *, const AllAttributesWrapper &,
AllTransitionsWrapper &, GraphicsStateGuardianBase *) {
AllTransitionsWrapper &, RenderTraverser *) {
return false;
}

View File

@ -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:

View File

@ -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;
}

View File

@ -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 &copy);
@ -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:

View File

@ -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();
}

View File

@ -8,11 +8,14 @@
#include <pandabase.h>
#include <arcChain.h>
#include <typeHandle.h>
#include <typedReferenceCount.h>
#include <notify.h>
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() {

View File

@ -7,6 +7,7 @@
#include "config_sgraphutil.h"
#include "frustumCullTraverser.h"
#include <wrt.h>
#include <geomNode.h>
#include <graphicsStateGuardian.h>
#include <geometricBoundingVolume.h>
@ -18,6 +19,8 @@
#include <transformTransition.h>
#include <allAttributesWrapper.h>
#include <allTransitionsWrapper.h>
#include <transformTransition.h>
#include <nodeTransitionWrapper.h>
#include <decalTransition.h>
#include <decalAttribute.h>
#include <pStatTimer.h>
@ -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);

View File

@ -36,7 +36,8 @@ class EXPCL_PANDA DirectRenderTraverser :
public RenderTraverser,
public TraverserVisitor<AllTransitionsWrapper, DirectRenderLevelState> {
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,

View File

@ -4,11 +4,11 @@
////////////////////////////////////////////////////////////////////
#include "frustumCullTraverser.h"
#include "get_rel_pos.h"
#include "config_sgraphutil.h"
#include <notify.h>
#include <nodeTransitionWrapper.h>
#include <transformTransition.h>
#include <wrt.h>
////////////////////////////////////////////////////////////////////
@ -18,7 +18,7 @@
////////////////////////////////////////////////////////////////////
template<class Visitor, class LevelState>
FrustumCullTraverser<Visitor, LevelState>::
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);
}
}

View File

@ -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<class Visitor, class AttributeWrapper, class LevelState>
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<Visitor, LevelState>
fct(root, visitor, initial_render_state,
fct(root, rel_from_camera, visitor, initial_render_state,
initial_level_state, gsg, graph_type);
}

View File

@ -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.

View File

@ -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:

View File

@ -12,12 +12,12 @@
#include <graphicsStateGuardian.h>
#include <get_rel_pos.h>
#include <dftraverser.h>
#include <luse.h>
#include <renderRelation.h>
#include <transformTransition.h>
#include <allAttributesWrapper.h>
#include <allTransitionsWrapper.h>
#include <renderTraverser.h>
////////////////////////////////////////////////////////////////////
// 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()) {

View File

@ -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:

View File

@ -16,6 +16,7 @@
#include <allAttributesWrapper.h>
#include <allTransitionsWrapper.h>
#include <renderRelation.h>
#include <renderTraverser.h>
////////////////////////////////////////////////////////////////////
// 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()) {

View File

@ -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:

View File

@ -17,6 +17,7 @@
#begin test_bin_target
#define TARGET chat
#define LOCAL_LIBS $[LOCAL_LIBS] chat
#define SOURCES \
chat_test.cxx

View File

@ -1,7 +1,6 @@
#include <eventHandler.h>
#include <chancfg.h>
#include <textNode.h>
#include <eggLoader.h>
#include <mouse.h>
#include <graphicsWindow.h>
#include <chatInput.h>
@ -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");

View File

@ -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);