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
// properties outside of this node's knowledge.
////////////////////////////////////////////////////////////////////
BoundingVolume *RopeNode::
void RopeNode::
reset_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;
do_recompute_bound(rel_to);
changed_internal_bound();
}
////////////////////////////////////////////////////////////////////
@ -229,7 +217,30 @@ reset_bound(const NodePath &rel_to) {
////////////////////////////////////////////////////////////////////
BoundingVolume *RopeNode::
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) {
PTA_Vertexf verts;
PTA_TexCoordf uvs;
PTA_Colorf colors;
PTA_int lengths;
int num_verts = get_num_segs() + 1;
@ -264,10 +276,13 @@ render_thread(CullTraverser *trav, CullTraverserData &data,
}
lengths.push_back(num_verts);
}
colors.push_back(Colorf(1.0f, 1.0f, 1.0f, 1.0f));
PT(Geom) geom = new GeomLinestrip;
geom->set_num_prims(num_segments);
geom->set_coords(verts);
geom->set_colors(colors, G_OVERALL);
geom->set_lengths(lengths);
CullableObject *object = new CullableObject(geom, data._state,
@ -346,6 +361,7 @@ render_billboard(CullTraverser *trav, CullTraverserData &data,
PTA_Vertexf verts;
PTA_TexCoordf uvs;
PTA_Colorf colors;
PTA_int lengths;
int vi = 0;
@ -404,6 +420,8 @@ render_billboard(CullTraverser *trav, CullTraverserData &data,
lengths.push_back(length * 2);
num_prims++;
}
colors.push_back(Colorf(1.0f, 1.0f, 1.0f, 1.0f));
PT(Geom) geom = new GeomTristrip;
geom->set_num_prims(num_prims);
@ -411,6 +429,7 @@ render_billboard(CullTraverser *trav, CullTraverserData &data,
if (uv_mode != UV_none) {
geom->set_texcoords(uvs, G_PER_VERTEX);
}
geom->set_colors(colors, G_OVERALL);
geom->set_lengths(lengths);
CullableObject *object = new CullableObject(geom, data._state,

View File

@ -54,13 +54,32 @@ public:
PUBLISHED:
enum RenderMode {
// Render the rope as a one-pixel thread using a linestrip.
RM_thread,
// Render the rope as a continuous triangle strip oriented to be
// perpendicular to the view vector.
RM_billboard
};
enum UVMode {
// Don't generate UV's along the curve.
UV_none,
// Generate UV's based on the parametric coordinates along the
// curve.
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,
// 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,
};
@ -82,12 +101,13 @@ PUBLISHED:
INLINE void set_thickness(float thickness);
INLINE float get_thickness() const;
BoundingVolume *reset_bound(const NodePath &rel_to);
void reset_bound(const NodePath &rel_to);
protected:
virtual BoundingVolume *recompute_internal_bound();
private:
BoundingVolume *do_recompute_bound(const NodePath &rel_to);
void render_thread(CullTraverser *trav, CullTraverserData &data,
NurbsCurveResult *result);
void render_billboard(CullTraverser *trav, CullTraverserData &data,

View File

@ -449,7 +449,7 @@ output(ostream &out) const {
if (_head == (NodePathComponent *)NULL) {
out << "(empty)";
} 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
// Access: Private

View File

@ -528,7 +528,6 @@ private:
CPT(RenderState) r_get_partial_state(NodePathComponent *comp, int n) const;
CPT(TransformState) r_get_net_transform(NodePathComponent *comp) 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,
const string &approx_path_str,

View File

@ -135,3 +135,9 @@ get_collapsed() const {
CDReader cdata(_cycler);
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;
}
////////////////////////////////////////////////////////////////////
// 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
// Access: Private

View File

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

View File

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

View File

@ -1644,6 +1644,29 @@ get_top_component(PandaNode *child_node, bool force) {
////////////////////////////////////////////////////////////////////
PT(NodePathComponent) PandaNode::
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();
if (num_parents == 0) {
// No parents; no ambiguity. This is the root.
@ -1654,7 +1677,7 @@ get_generic_component(bool accept_ambiguity) {
if (num_parents == 1) {
// Only one parent; no ambiguity.
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);
} else {
@ -1664,11 +1687,10 @@ get_generic_component(bool accept_ambiguity) {
<< *this << " has " << num_parents
<< " parents; choosing arbitrary path to root.\n";
}
ambiguity_detected = true;
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);
nassertr(accept_ambiguity || !unambiguous_graph, result);
}
return result;

View File

@ -206,6 +206,7 @@ private:
static PT(NodePathComponent) get_top_component(PandaNode *child,
bool force);
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);
static void sever_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. So we update them together.
CollideMask _net_collide_mask;
bool _fixed_internal_bound;
};
PipelineCycler<CData> _cycler;