a few more interfaces for pgraph pgui

This commit is contained in:
David Rose 2002-03-14 17:20:01 +00:00
parent ac8ab3b258
commit 98285edbeb
4 changed files with 332 additions and 3 deletions

View File

@ -697,7 +697,7 @@ class DirectGuiWidget(DirectGuiBase, NodePath):
DirectGuiBase.__init__(self) DirectGuiBase.__init__(self)
NodePath.__init__(self) NodePath.__init__(self)
# Create a button # Create a button
self.guiItem = self['pgFunc']() self.guiItem = self['pgFunc']('')
# Override automatically generated guiId # Override automatically generated guiId
if self['guiId']: if self['guiId']:
self.guiItem.setId(self['guiId']) self.guiItem.setId(self['guiId'])

View File

@ -91,7 +91,7 @@ class OnscreenText(PandaObject, NodePath):
""" """
# make a text node # make a text node
textNode = TextNode() textNode = TextNode('')
self.textNode = textNode self.textNode = textNode
# We ARE a node path. Initially, we're an empty node path. # We ARE a node path. Initially, we're an empty node path.

View File

@ -33,6 +33,8 @@
#include "look_at.h" #include "look_at.h"
#include "compose_matrix.h" #include "compose_matrix.h"
#include "plist.h" #include "plist.h"
#include "boundingSphere.h"
#include "qpgeomNode.h"
// stack seems to overflow on Intel C++ at 7000. If we need more than // stack seems to overflow on Intel C++ at 7000. If we need more than
// 7000, need to increase stack size. // 7000, need to increase stack size.
@ -2219,11 +2221,267 @@ verify_complete() const {
return length == 0 && node->get_num_parents() == 0; return length == 0 && node->get_num_parents() == 0;
} }
////////////////////////////////////////////////////////////////////
// Function: qpNodePath::prepare_scene
// Access: Published
// Description: Walks through the scene graph beginning at the bottom
// node, and does whatever initialization is required to
// render the scene properly with the indicated GSG. It
// is not strictly necessary to call this, since the GSG
// will initialize itself when the scene is rendered,
// but this may take some of the overhead away from that
// process.
//
// If force_retained_mode is true, retained mode is set
// on the geometry encountered, regardless of the
// setting of the retained-mode Config variable.
// Otherwise, retained mode is set only if the
// retained-mode Config variable is true.
////////////////////////////////////////////////////////////////////
void qpNodePath::
prepare_scene(GraphicsStateGuardianBase *gsg, bool force_retained_mode) {
nassertv_always(!is_empty());
// **** do something.
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePath::show_bounds
// Access: Published
// Description: Causes the bounding volume of the bottom node and all
// of its descendants (that is, the bounding volume
// associated with the the bottom arc) to be rendered,
// if possible. The rendering method is less than
// optimal; this is intended primarily for debugging.
////////////////////////////////////////////////////////////////////
void qpNodePath::
show_bounds() {
nassertv_always(!is_empty());
nassertv(false);
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePath::hide_bounds
// Access: Published
// Description: Stops the rendering of the bounding volume begun with
// show_bounds().
////////////////////////////////////////////////////////////////////
void qpNodePath::
hide_bounds() {
nassertv_always(!is_empty());
nassertv(false);
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePath::get_bounds
// Access: Published
// Description: Returns a newly-allocated bounding volume containing
// the bottom node and all of its descendants. This is
// the bounding volume on the bottom arc, converted to
// the local coordinate space of the node.
////////////////////////////////////////////////////////////////////
PT(BoundingVolume) qpNodePath::
get_bounds() const {
nassertr(!is_empty(), new BoundingSphere);
PandaNode *this_node = node();
PT(BoundingVolume) bv = this_node->get_bound().make_copy();
if (bv->is_of_type(GeometricBoundingVolume::get_class_type()) &&
!this_node->get_transform()->is_identity()) {
// The bounding volume has already been transformed by the node's
// matrix. We'd rather return a bounding volume in the node's
// space, so we have to untransform it now. Ick.
GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, bv);
const LMatrix4f &mat = get_parent().get_mat(*this);
gbv->xform(mat);
}
return bv;
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePath::write_bounds
// Access: Published
// Description: Writes a description of the bounding volume
// containing the bottom node and all of its descendants
// to the indicated output stream.
////////////////////////////////////////////////////////////////////
void qpNodePath::
write_bounds(ostream &out) const {
get_bounds()->write(out);
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePath::calc_tight_bounds
// Access: Published
// Description: Calculates the minimum and maximum vertices of all
// Geoms at this qpNodePath's bottom node and below. This
// is a tight bounding box; it will generally be tighter
// than the bounding volume returned by get_bounds()
// (but it is more expensive to compute).
//
// The return value is true if any points are within the
// bounding volume, or false if none are.
////////////////////////////////////////////////////////////////////
bool qpNodePath::
calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point) {
min_point.set(0.0f, 0.0f, 0.0f);
max_point.set(0.0f, 0.0f, 0.0f);
nassertr_always(!is_empty(), false);
bool found_any = false;
r_calc_tight_bounds(node(), min_point, max_point, found_any,
TransformState::make_identity());
return found_any;
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePath::flatten_light
// Access: Published
// Description: Lightly flattens out the hierarchy below this node by
// applying transforms, colors, and texture matrices
// from the arcs onto the vertices, but does not remove
// any nodes.
//
// This can result in improved rendering performance
// because there will be fewer transforms in the
// resulting scene graph, but the number of nodes will
// remain the same.
//
// Particularly, any qpNodePaths that reference nodes
// within this hierarchy will not be damaged. However,
// since this operation will remove transforms from the
// scene graph, it may be dangerous to apply to arcs
// where you expect to dynamically modify the transform,
// or where you expect the geometry to remain in a
// particular local coordinate system.
//
// The return value is always 0, since flatten_light
// does not remove any arcs.
////////////////////////////////////////////////////////////////////
int qpNodePath::
flatten_light() {
nassertr(!is_empty(), 0);
/*
SceneGraphReducer gr(_graph_type);
gr.apply_transitions(arc());
*/
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePath::flatten_medium
// Access: Published
// Description: A more thorough flattening than flatten_light(), this
// first applies all the transforms, colors, and texture
// matrices from the arcs onto the vertices, and then
// removes unneeded grouping nodes--nodes that have
// exactly one child, for instance, but have no special
// properties in themselves.
//
// This results in improved perforamance over
// flatten_light() because the number of nodes in the
// scene graph is reduced.
//
// If max_children is specified, it represents the
// maximum number of children a node is allowed to have
// and still be flattened. Normally, this is 1; we
// don't typically want to flatten a node that has
// multiple children. However, sometimes this may be
// desirable; set this parameter to control the limit.
// If this is set to -1, there is no limit.
//
// The return value is the number of arcs removed.
////////////////////////////////////////////////////////////////////
int qpNodePath::
flatten_medium(int max_children) {
nassertr(!is_empty(), 0);
/*
SceneGraphReducer gr(_graph_type);
gr.set_max_children(max_children);
gr.apply_transitions(arc());
int num_removed = gr.flatten(node(), false);
return num_removed;
*/
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePath::flatten_strong
// Access: Published
// Description: The strongest possible flattening. This first
// applies all of the transforms to the vertices, as in
// flatten_medium(), but then it will combine sibling
// nodes together when possible, in addition to removing
// unnecessary parent-child nodes. This can result in
// substantially fewer nodes, but any nicely-grouped
// hierachical bounding volumes may be lost.
//
// It is generally a good idea to apply this kind of
// flattening only to nodes that will be culled largely
// as a single unit, like a car. Applying this to an
// entire scene may result in overall poorer performance
// because of less-effective culling.
////////////////////////////////////////////////////////////////////
int qpNodePath::
flatten_strong(int max_children) {
nassertr(!is_empty(), 0);
/*
SceneGraphReducer gr(_graph_type);
gr.set_max_children(max_children);
gr.apply_transitions(arc());
int num_removed = gr.flatten(node(), true);
return num_removed;
*/
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePath::write_bam_file
// Access: Published
// Description: Writes the contents of this node and below out to a
// bam file with the indicated filename. This file may
// then be read in again, as is, at some later point.
// Returns true if successful, false on some kind of
// error.
////////////////////////////////////////////////////////////////////
bool qpNodePath::
write_bam_file(const string &filename) const {
nassertr(!is_empty(), false);
/*
BamFile bam_file;
bool okflag = false;
if (bam_file.open_write(filename)) {
if (bam_file.write_object(node())) {
okflag = true;
}
bam_file.close();
}
return okflag;
*/
// At the moment, we can't do this because BamFile is defined in
// loader and loader depends on pgraph.
nassertr(false, false);
return false;
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: qpNodePath::uncollapse_head // Function: qpNodePath::uncollapse_head
// Access: Private // Access: Private
// Description: Quietly and transparently uncollapses the _head // Description: Quietly and transparently uncollapses the _head
// pointer if it needs it. // pointer if it needs it. This can happen only when
// two distinct NodePaths are collapsed into the same
// path after the removal of an instance somewhere
// higher up the chain.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void qpNodePath:: void qpNodePath::
uncollapse_head() const { uncollapse_head() const {
@ -2490,3 +2748,55 @@ r_adjust_all_priorities(PandaNode *node, int adjustment) {
r_adjust_all_priorities(cr.get_child(i), adjustment); r_adjust_all_priorities(cr.get_child(i), adjustment);
} }
} }
////////////////////////////////////////////////////////////////////
// Function: qpNodePath::r_calc_tight_bounds
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
void qpNodePath::
r_calc_tight_bounds(PandaNode *node, LPoint3f &min_point, LPoint3f &max_point,
bool &found_any, const TransformState *transform) {
CPT(TransformState) next_transform =
transform->compose(node->get_transform());
if (node->is_geom_node()) {
qpGeomNode *gnode;
DCAST_INTO_V(gnode, node);
const LMatrix4f &mat = next_transform->get_mat();
int num_geoms = gnode->get_num_geoms();
for (int i = 0; i < num_geoms; i++) {
Geom *geom = gnode->get_geom(i);
Geom::VertexIterator vi = geom->make_vertex_iterator();
int num_prims = geom->get_num_prims();
for (int p = 0; p < num_prims; p++) {
int length = geom->get_length(p);
for (int v = 0; v < length; v++) {
Vertexf vertex = geom->get_next_vertex(vi) * mat;
if (found_any) {
min_point.set(min(min_point[0], vertex[0]),
min(min_point[1], vertex[1]),
min(min_point[2], vertex[2]));
max_point.set(max(max_point[0], vertex[0]),
max(max_point[1], vertex[1]),
max(max_point[2], vertex[2]));
} else {
min_point = vertex;
max_point = vertex;
found_any = true;
}
}
}
}
}
// Now consider children.
PandaNode::Children cr = node->get_children();
int num_children = cr.get_num_children();
for (int i = 0; i < num_children; i++) {
r_calc_tight_bounds(cr.get_child(i), min_point, max_point,
found_any, next_transform);
}
}

View File

@ -465,8 +465,23 @@ PUBLISHED:
INLINE bool operator < (const qpNodePath &other) const; INLINE bool operator < (const qpNodePath &other) const;
INLINE int compare_to(const qpNodePath &other) const; INLINE int compare_to(const qpNodePath &other) const;
// Miscellaneous
bool verify_complete() const; bool verify_complete() const;
void prepare_scene(GraphicsStateGuardianBase *gsg, bool force_retained_mode = false);
void show_bounds();
void hide_bounds();
PT(BoundingVolume) get_bounds() const;
void write_bounds(ostream &out) const;
bool calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point);
int flatten_light();
int flatten_medium(int max_children = 1);
int flatten_strong(int max_children = 1);
bool write_bam_file(const string &filename) const;
private: private:
void uncollapse_head() const; void uncollapse_head() const;
static void find_common_ancestor(const qpNodePath &a, const qpNodePath &b, static void find_common_ancestor(const qpNodePath &a, const qpNodePath &b,
@ -490,6 +505,10 @@ private:
void r_adjust_all_priorities(PandaNode *node, int adjustment); void r_adjust_all_priorities(PandaNode *node, int adjustment);
void r_calc_tight_bounds(PandaNode *node,
LPoint3f &min_point, LPoint3f &max_point,
bool &found_any, const TransformState *transform);
PT(qpNodePathComponent) _head; PT(qpNodePathComponent) _head;
ErrorType _error_type; ErrorType _error_type;
static int _max_search_depth; static int _max_search_depth;