mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 16:58:40 -04:00
don't automatically recompute explicit bounding volumes
This commit is contained in:
parent
e211aa9294
commit
673c162389
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 ©) :
|
||||
_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();
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user