don't automatically recompute explicit bounding volumes

This commit is contained in:
David Rose 2002-12-06 20:17:00 +00:00
parent e211aa9294
commit 673c162389
10 changed files with 143 additions and 62 deletions

View File

@ -201,22 +201,10 @@ write(ostream &out, int indent_level) const {
// called explicitly when the curve has changed // called explicitly when the curve has changed
// properties outside of this node's knowledge. // properties outside of this node's knowledge.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
BoundingVolume *RopeNode:: void RopeNode::
reset_bound(const NodePath &rel_to) { reset_bound(const NodePath &rel_to) {
// First, get ourselves a fresh, empty bounding volume. do_recompute_bound(rel_to);
BoundingVolume *bound = PandaNode::recompute_internal_bound(); changed_internal_bound();
nassertr(bound != (BoundingVolume *)NULL, bound);
NurbsCurveEvaluator *curve = get_curve();
if (curve != (NurbsCurveEvaluator *)NULL) {
pvector<LPoint3f> verts;
get_curve()->get_vertices(verts, rel_to);
GeometricBoundingVolume *gbv;
DCAST_INTO_R(gbv, bound, bound);
gbv->around(&verts[0], &verts[verts.size() - 1]);
}
return bound;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -229,7 +217,30 @@ reset_bound(const NodePath &rel_to) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
BoundingVolume *RopeNode:: BoundingVolume *RopeNode::
recompute_internal_bound() { recompute_internal_bound() {
return reset_bound(NodePath(this)); return do_recompute_bound(NodePath(this));
}
////////////////////////////////////////////////////////////////////
// Function: RopeNode::do_recompute_bound
// Access: Private
// Description: Does the actual internal recompute.
////////////////////////////////////////////////////////////////////
BoundingVolume *RopeNode::
do_recompute_bound(const NodePath &rel_to) {
// First, get ourselves a fresh, empty bounding volume.
BoundingVolume *bound = PandaNode::recompute_internal_bound();
nassertr(bound != (BoundingVolume *)NULL, bound);
NurbsCurveEvaluator *curve = get_curve();
if (curve != (NurbsCurveEvaluator *)NULL) {
pvector<LPoint3f> verts;
get_curve()->get_vertices(verts, rel_to);
GeometricBoundingVolume *gbv;
DCAST_INTO_R(gbv, bound, bound);
gbv->around(&verts[0], &verts[verts.size() - 1]);
}
return bound;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -250,6 +261,7 @@ render_thread(CullTraverser *trav, CullTraverserData &data,
NurbsCurveResult *result) { NurbsCurveResult *result) {
PTA_Vertexf verts; PTA_Vertexf verts;
PTA_TexCoordf uvs; PTA_TexCoordf uvs;
PTA_Colorf colors;
PTA_int lengths; PTA_int lengths;
int num_verts = get_num_segs() + 1; int num_verts = get_num_segs() + 1;
@ -264,10 +276,13 @@ render_thread(CullTraverser *trav, CullTraverserData &data,
} }
lengths.push_back(num_verts); lengths.push_back(num_verts);
} }
colors.push_back(Colorf(1.0f, 1.0f, 1.0f, 1.0f));
PT(Geom) geom = new GeomLinestrip; PT(Geom) geom = new GeomLinestrip;
geom->set_num_prims(num_segments); geom->set_num_prims(num_segments);
geom->set_coords(verts); geom->set_coords(verts);
geom->set_colors(colors, G_OVERALL);
geom->set_lengths(lengths); geom->set_lengths(lengths);
CullableObject *object = new CullableObject(geom, data._state, CullableObject *object = new CullableObject(geom, data._state,
@ -346,6 +361,7 @@ render_billboard(CullTraverser *trav, CullTraverserData &data,
PTA_Vertexf verts; PTA_Vertexf verts;
PTA_TexCoordf uvs; PTA_TexCoordf uvs;
PTA_Colorf colors;
PTA_int lengths; PTA_int lengths;
int vi = 0; int vi = 0;
@ -404,6 +420,8 @@ render_billboard(CullTraverser *trav, CullTraverserData &data,
lengths.push_back(length * 2); lengths.push_back(length * 2);
num_prims++; num_prims++;
} }
colors.push_back(Colorf(1.0f, 1.0f, 1.0f, 1.0f));
PT(Geom) geom = new GeomTristrip; PT(Geom) geom = new GeomTristrip;
geom->set_num_prims(num_prims); geom->set_num_prims(num_prims);
@ -411,6 +429,7 @@ render_billboard(CullTraverser *trav, CullTraverserData &data,
if (uv_mode != UV_none) { if (uv_mode != UV_none) {
geom->set_texcoords(uvs, G_PER_VERTEX); geom->set_texcoords(uvs, G_PER_VERTEX);
} }
geom->set_colors(colors, G_OVERALL);
geom->set_lengths(lengths); geom->set_lengths(lengths);
CullableObject *object = new CullableObject(geom, data._state, CullableObject *object = new CullableObject(geom, data._state,

View File

@ -54,13 +54,32 @@ public:
PUBLISHED: PUBLISHED:
enum RenderMode { enum RenderMode {
// Render the rope as a one-pixel thread using a linestrip.
RM_thread, RM_thread,
// Render the rope as a continuous triangle strip oriented to be
// perpendicular to the view vector.
RM_billboard RM_billboard
}; };
enum UVMode { enum UVMode {
// Don't generate UV's along the curve.
UV_none, UV_none,
// Generate UV's based on the parametric coordinates along the
// curve.
UV_parametric, UV_parametric,
// Generate UV's in proportion to spatial distance along the
// curve, by using the distance function to compute the length of
// each segment.
UV_distance, UV_distance,
// As above, but don't bother to take the square root of each
// segment. The distance is then in proportion to the
// sum-of-squares of the segments along the rope. If the segments
// are similar in length, this approximates the proportion of
// UV_distance while avoiding hundreds of square root operations.
UV_distance2, UV_distance2,
}; };
@ -82,12 +101,13 @@ PUBLISHED:
INLINE void set_thickness(float thickness); INLINE void set_thickness(float thickness);
INLINE float get_thickness() const; INLINE float get_thickness() const;
BoundingVolume *reset_bound(const NodePath &rel_to); void reset_bound(const NodePath &rel_to);
protected: protected:
virtual BoundingVolume *recompute_internal_bound(); virtual BoundingVolume *recompute_internal_bound();
private: private:
BoundingVolume *do_recompute_bound(const NodePath &rel_to);
void render_thread(CullTraverser *trav, CullTraverserData &data, void render_thread(CullTraverser *trav, CullTraverserData &data,
NurbsCurveResult *result); NurbsCurveResult *result);
void render_billboard(CullTraverser *trav, CullTraverserData &data, void render_billboard(CullTraverser *trav, CullTraverserData &data,

View File

@ -449,7 +449,7 @@ output(ostream &out) const {
if (_head == (NodePathComponent *)NULL) { if (_head == (NodePathComponent *)NULL) {
out << "(empty)"; out << "(empty)";
} else { } else {
r_output(out, _head); _head->output(out);
} }
} }
@ -3042,43 +3042,6 @@ r_get_partial_transform(NodePathComponent *comp, int n) const {
} }
} }
////////////////////////////////////////////////////////////////////
// Function: NodePath::r_output
// Access: Private
// Description: The recursive implementation of output(), this writes
// the names of each node component in order from
// beginning to end, by first walking to the end of the
// linked list and then outputting from there.
////////////////////////////////////////////////////////////////////
void NodePath::
r_output(ostream &out, NodePathComponent *comp) const {
PandaNode *node = comp->get_node();
NodePathComponent *next = comp->get_next();
if (next != (NodePathComponent *)NULL) {
// This is not the head of the list; keep going up.
r_output(out, next);
out << "/";
PandaNode *parent_node = next->get_node();
if (parent_node->find_stashed(node) >= 0) {
// The node is stashed.
out << "@@";
} else if (node->find_parent(parent_node) < 0) {
// Oops, there's an error. This shouldn't happen.
out << ".../";
}
}
// Now output this component.
if (node->has_name()) {
out << node->get_name();
} else {
out << "-" << node->get_type();
}
// out << "[" << comp->get_length() << "]";
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: NodePath::find_matches // Function: NodePath::find_matches
// Access: Private // Access: Private

View File

@ -528,7 +528,6 @@ private:
CPT(RenderState) r_get_partial_state(NodePathComponent *comp, int n) const; CPT(RenderState) r_get_partial_state(NodePathComponent *comp, int n) const;
CPT(TransformState) r_get_net_transform(NodePathComponent *comp) const; CPT(TransformState) r_get_net_transform(NodePathComponent *comp) const;
CPT(TransformState) r_get_partial_transform(NodePathComponent *comp, int n) const; CPT(TransformState) r_get_partial_transform(NodePathComponent *comp, int n) const;
void r_output(ostream &out, NodePathComponent *comp) const;
void find_matches(NodePathCollection &result, void find_matches(NodePathCollection &result,
const string &approx_path_str, const string &approx_path_str,

View File

@ -135,3 +135,9 @@ get_collapsed() const {
CDReader cdata(_cycler); CDReader cdata(_cycler);
return cdata->_next; return cdata->_next;
} }
INLINE ostream &operator << (ostream &out, const NodePathComponent &comp) {
comp.output(out);
return out;
}

View File

@ -162,6 +162,43 @@ uncollapse() {
return comp; return comp;
} }
////////////////////////////////////////////////////////////////////
// Function: NodePathComponent::output
// Access: Public
// Description: The recursive implementation of NodePath::output(),
// this writes the names of each node component in order
// from beginning to end, by first walking to the end of
// the linked list and then outputting from there.
////////////////////////////////////////////////////////////////////
void NodePathComponent::
output(ostream &out) const {
PandaNode *node = this->get_node();
NodePathComponent *next = this->get_next();
if (next != (NodePathComponent *)NULL) {
// This is not the head of the list; keep going up.
next->output(out);
out << "/";
PandaNode *parent_node = next->get_node();
if (parent_node->find_stashed(node) >= 0) {
// The node is stashed.
out << "@@";
} else if (node->find_parent(parent_node) < 0) {
// Oops, there's an error. This shouldn't happen.
out << ".../";
}
}
// Now output this component.
if (node->has_name()) {
out << node->get_name();
} else {
out << "-" << node->get_type();
}
// out << "[" << this->get_length() << "]";
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: NodePathComponent::set_next // Function: NodePathComponent::set_next
// Access: Private // Access: Private

View File

@ -64,6 +64,8 @@ public:
bool fix_length(); bool fix_length();
NodePathComponent *uncollapse(); NodePathComponent *uncollapse();
void output(ostream &out) const;
private: private:
void set_next(NodePathComponent *next); void set_next(NodePathComponent *next);
@ -109,6 +111,8 @@ private:
friend class PandaNode; friend class PandaNode;
}; };
INLINE ostream &operator << (ostream &out, const NodePathComponent &comp);
#include "nodePathComponent.I" #include "nodePathComponent.I"
#endif #endif

View File

@ -120,6 +120,7 @@ CData() {
_transform = TransformState::make_identity(); _transform = TransformState::make_identity();
_draw_mask = DrawMask::all_on(); _draw_mask = DrawMask::all_on();
_net_collide_mask = CollideMask::all_off(); _net_collide_mask = CollideMask::all_off();
_fixed_internal_bound = false;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -136,7 +137,8 @@ CData(const PandaNode::CData &copy) :
_state(copy._state), _state(copy._state),
_effects(copy._effects), _effects(copy._effects),
_transform(copy._transform), _transform(copy._transform),
_draw_mask(copy._draw_mask) _draw_mask(copy._draw_mask),
_fixed_internal_bound(copy._fixed_internal_bound)
{ {
_net_collide_mask = CollideMask::all_off(); _net_collide_mask = CollideMask::all_off();
} }
@ -719,6 +721,8 @@ get_net_collide_mask() const {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE void PandaNode:: INLINE void PandaNode::
set_bound(BoundingVolumeType type) { set_bound(BoundingVolumeType type) {
CDWriter cdata(_cycler);
cdata->_fixed_internal_bound = false;
BoundedObject::set_bound(type); BoundedObject::set_bound(type);
} }
@ -733,6 +737,8 @@ set_bound(BoundingVolumeType type) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE void PandaNode:: INLINE void PandaNode::
set_bound(const BoundingVolume &volume) { set_bound(const BoundingVolume &volume) {
CDWriter cdata(_cycler);
cdata->_fixed_internal_bound = true;
_internal_bound.set_bound(volume); _internal_bound.set_bound(volume);
changed_internal_bound(); changed_internal_bound();
} }
@ -758,7 +764,9 @@ get_bound() const {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE const BoundingVolume &PandaNode:: INLINE const BoundingVolume &PandaNode::
get_internal_bound() const { get_internal_bound() const {
if (is_bound_stale() || _internal_bound.is_bound_stale()) { CDReader cdata(_cycler);
if (!cdata->_fixed_internal_bound &&
(is_bound_stale() || _internal_bound.is_bound_stale())) {
((PandaNode *)this)->recompute_internal_bound(); ((PandaNode *)this)->recompute_internal_bound();
} }
return _internal_bound.get_bound(); return _internal_bound.get_bound();

View File

@ -1644,6 +1644,29 @@ get_top_component(PandaNode *child_node, bool force) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
PT(NodePathComponent) PandaNode:: PT(NodePathComponent) PandaNode::
get_generic_component(bool accept_ambiguity) { get_generic_component(bool accept_ambiguity) {
bool ambiguity_detected = false;
PT(NodePathComponent) result =
r_get_generic_component(accept_ambiguity, ambiguity_detected);
if (!accept_ambiguity && ambiguity_detected) {
pgraph_cat.warning()
<< "Chose: " << *result << "\n";
nassertr(!unambiguous_graph, result);
}
return result;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::r_get_generic_component
// Access: Private
// Description: The recursive implementation of
// get_generic_component, this simply sets the flag when
// the ambiguity is detected (so we can report the
// bottom node that started the ambiguous search).
////////////////////////////////////////////////////////////////////
PT(NodePathComponent) PandaNode::
r_get_generic_component(bool accept_ambiguity, bool &ambiguity_detected) {
int num_parents = get_num_parents(); int num_parents = get_num_parents();
if (num_parents == 0) { if (num_parents == 0) {
// No parents; no ambiguity. This is the root. // No parents; no ambiguity. This is the root.
@ -1654,7 +1677,7 @@ get_generic_component(bool accept_ambiguity) {
if (num_parents == 1) { if (num_parents == 1) {
// Only one parent; no ambiguity. // Only one parent; no ambiguity.
PT(NodePathComponent) parent = PT(NodePathComponent) parent =
get_parent(0)->get_generic_component(accept_ambiguity); get_parent(0)->r_get_generic_component(accept_ambiguity, ambiguity_detected);
result = get_component(parent, this); result = get_component(parent, this);
} else { } else {
@ -1664,11 +1687,10 @@ get_generic_component(bool accept_ambiguity) {
<< *this << " has " << num_parents << *this << " has " << num_parents
<< " parents; choosing arbitrary path to root.\n"; << " parents; choosing arbitrary path to root.\n";
} }
ambiguity_detected = true;
PT(NodePathComponent) parent = PT(NodePathComponent) parent =
get_parent(0)->get_generic_component(accept_ambiguity); get_parent(0)->r_get_generic_component(accept_ambiguity, ambiguity_detected);
result = get_component(parent, this); result = get_component(parent, this);
nassertr(accept_ambiguity || !unambiguous_graph, result);
} }
return result; return result;

View File

@ -206,6 +206,7 @@ private:
static PT(NodePathComponent) get_top_component(PandaNode *child, static PT(NodePathComponent) get_top_component(PandaNode *child,
bool force); bool force);
PT(NodePathComponent) get_generic_component(bool accept_ambiguity); PT(NodePathComponent) get_generic_component(bool accept_ambiguity);
PT(NodePathComponent) r_get_generic_component(bool accept_ambiguity, bool &ambiguity_detected);
void delete_component(NodePathComponent *component); void delete_component(NodePathComponent *component);
static void sever_connection(PandaNode *parent_node, PandaNode *child_node); static void sever_connection(PandaNode *parent_node, PandaNode *child_node);
static void new_connection(PandaNode *parent_node, PandaNode *child_node); static void new_connection(PandaNode *parent_node, PandaNode *child_node);
@ -292,6 +293,8 @@ private:
// updated for the same reasons the bounding volume needs to be // updated for the same reasons the bounding volume needs to be
// updated. So we update them together. // updated. So we update them together.
CollideMask _net_collide_mask; CollideMask _net_collide_mask;
bool _fixed_internal_bound;
}; };
PipelineCycler<CData> _cycler; PipelineCycler<CData> _cycler;