From 5e8855ebc897cc06d658952e5f22ca3cd2147bc6 Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 29 Apr 2005 23:06:27 +0000 Subject: [PATCH] fix calc_tight_bounds(), add NodePath::show_tight_bounds() --- panda/src/gobj/qpgeomPrimitive.cxx | 8 +- panda/src/pgraph/cullTraverser.cxx | 106 ++++++++++++++++++++++---- panda/src/pgraph/cullTraverser.h | 3 +- panda/src/pgraph/geomNode.cxx | 2 +- panda/src/pgraph/nodePath.cxx | 18 ++++- panda/src/pgraph/nodePath.h | 1 + panda/src/pgraph/renderEffects.I | 17 +++++ panda/src/pgraph/renderEffects.cxx | 4 + panda/src/pgraph/renderEffects.h | 10 ++- panda/src/pgraph/showBoundsEffect.I | 16 +++- panda/src/pgraph/showBoundsEffect.cxx | 26 ++----- panda/src/pgraph/showBoundsEffect.h | 8 +- 12 files changed, 171 insertions(+), 48 deletions(-) diff --git a/panda/src/gobj/qpgeomPrimitive.cxx b/panda/src/gobj/qpgeomPrimitive.cxx index 61aefbde89..d39790129a 100644 --- a/panda/src/gobj/qpgeomPrimitive.cxx +++ b/panda/src/gobj/qpgeomPrimitive.cxx @@ -1142,7 +1142,7 @@ calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, if (got_mat) { for (int i = 0; i < cdata->_num_vertices; i++) { reader.set_row(cdata->_first_vertex + i); - const LVecBase3f &vertex = reader.get_data3f(); + LPoint3f vertex = mat.xform_point(reader.get_data3f()); if (found_any) { min_point.set(min(min_point[0], vertex[0]), @@ -1160,7 +1160,7 @@ calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, } else { for (int i = 0; i < cdata->_num_vertices; i++) { reader.set_row(cdata->_first_vertex + i); - LPoint3f vertex = mat.xform_point(reader.get_data3f()); + const LVecBase3f &vertex = reader.get_data3f(); if (found_any) { min_point.set(min(min_point[0], vertex[0]), @@ -1184,7 +1184,7 @@ calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, if (got_mat) { while (!index.is_at_end()) { reader.set_row(index.get_data1i()); - const LVecBase3f &vertex = reader.get_data3f(); + LPoint3f vertex = mat.xform_point(reader.get_data3f()); if (found_any) { min_point.set(min(min_point[0], vertex[0]), @@ -1202,7 +1202,7 @@ calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, } else { while (!index.is_at_end()) { reader.set_row(index.get_data1i()); - LPoint3f vertex = mat.xform_point(reader.get_data3f()); + const LVecBase3f &vertex = reader.get_data3f(); if (found_any) { min_point.set(min(min_point[0], vertex[0]), diff --git a/panda/src/pgraph/cullTraverser.cxx b/panda/src/pgraph/cullTraverser.cxx index 55ae90a86f..40101de4fb 100644 --- a/panda/src/pgraph/cullTraverser.cxx +++ b/panda/src/pgraph/cullTraverser.cxx @@ -35,6 +35,7 @@ #include "portalClipper.h" #include "qpgeom.h" #include "qpgeomTristrips.h" +#include "qpgeomLinestrips.h" #include "qpgeomVertexWriter.h" PStatCollector CullTraverser::_nodes_pcollector("Nodes"); @@ -166,7 +167,7 @@ traverse(CullTraverserData &data) { if (node_effects->has_show_bounds()) { // If we should show the bounding volume for this node, make it // up now. - show_bounds(data); + show_bounds(data, node_effects->has_show_tight_bounds()); } data.apply_transform_and_state(this); @@ -267,21 +268,35 @@ traverse_below(CullTraverserData &data) { // external bounding volume. //////////////////////////////////////////////////////////////////// void CullTraverser:: -show_bounds(CullTraverserData &data) { +show_bounds(CullTraverserData &data, bool tight) { PandaNode *node = data.node(); - PT(Geom) bounds_viz = make_bounds_viz(node->get_bound()); - if (bounds_viz != (Geom *)NULL) { - _geoms_pcollector.add_level(2); - CullableObject *outer_viz = - new CullableObject(bounds_viz, get_bounds_outer_viz_state(), - data._render_transform); - _cull_handler->record_object(outer_viz, this); + if (tight) { + PT(Geom) bounds_viz = make_tight_bounds_viz(node); - CullableObject *inner_viz = - new CullableObject(bounds_viz, get_bounds_inner_viz_state(), - data._render_transform); - _cull_handler->record_object(inner_viz, this); + if (bounds_viz != (Geom *)NULL) { + _geoms_pcollector.add_level(1); + CullableObject *outer_viz = + new CullableObject(bounds_viz, get_bounds_outer_viz_state(), + data._render_transform); + _cull_handler->record_object(outer_viz, this); + } + + } else { + PT(Geom) bounds_viz = make_bounds_viz(node->get_bound()); + + if (bounds_viz != (Geom *)NULL) { + _geoms_pcollector.add_level(2); + CullableObject *outer_viz = + new CullableObject(bounds_viz, get_bounds_outer_viz_state(), + data._render_transform); + _cull_handler->record_object(outer_viz, this); + + CullableObject *inner_viz = + new CullableObject(bounds_viz, get_bounds_inner_viz_state(), + data._render_transform); + _cull_handler->record_object(inner_viz, this); + } } } @@ -305,7 +320,7 @@ make_bounds_viz(const BoundingVolume &vol) { static const int num_stacks = 8; PT(qpGeomVertexData) vdata = new qpGeomVertexData - ("collision", qpGeomVertexFormat::get_v3(), + ("bounds", qpGeomVertexFormat::get_v3(), qpGeom::UH_stream); qpGeomVertexWriter vertex(vdata, InternalName::get_vertex()); @@ -350,6 +365,67 @@ make_bounds_viz(const BoundingVolume &vol) { return geom; } +//////////////////////////////////////////////////////////////////// +// Function: CullTraverser::make_tight_bounds_viz +// Access: Private +// Description: Returns a bounding-box visualization of the indicated +// node's "tight" bounding volume. +//////////////////////////////////////////////////////////////////// +PT(Geom) CullTraverser:: +make_tight_bounds_viz(PandaNode *node) { + PT(Geom) geom; + + NodePath np = NodePath::any_path(node); + + LPoint3f n, x; + bool found_any = false; + node->calc_tight_bounds(n, x, found_any, TransformState::make_identity()); + if (found_any) { + PT(qpGeomVertexData) vdata = new qpGeomVertexData + ("bounds", qpGeomVertexFormat::get_v3(), + qpGeom::UH_stream); + qpGeomVertexWriter vertex(vdata, InternalName::get_vertex()); + + vertex.add_data3f(n[0], n[1], n[2]); + vertex.add_data3f(n[0], n[1], x[2]); + vertex.add_data3f(n[0], x[1], n[2]); + vertex.add_data3f(n[0], x[1], x[2]); + vertex.add_data3f(x[0], n[1], n[2]); + vertex.add_data3f(x[0], n[1], x[2]); + vertex.add_data3f(x[0], x[1], n[2]); + vertex.add_data3f(x[0], x[1], x[2]); + + PT(qpGeomLinestrips) strip = new qpGeomLinestrips(qpGeom::UH_stream); + + // We wind one long linestrip around the wireframe cube. This + // does require backtracking a few times here and there. + strip->add_vertex(0); + strip->add_vertex(1); + strip->add_vertex(3); + strip->add_vertex(2); + strip->add_vertex(0); + strip->add_vertex(4); + strip->add_vertex(5); + strip->add_vertex(7); + strip->add_vertex(6); + strip->add_vertex(4); + strip->add_vertex(6); + strip->add_vertex(2); + strip->add_vertex(3); + strip->add_vertex(7); + strip->add_vertex(5); + strip->add_vertex(1); + strip->close_primitive(); + + PT(qpGeom) qpgeom = new qpGeom; + qpgeom->set_vertex_data(vdata); + qpgeom->add_primitive(strip); + geom = qpgeom.p(); + } + + return geom; +} + //////////////////////////////////////////////////////////////////// // Function: CullTraverser::compute_point // Access: Private, Static @@ -508,7 +584,7 @@ r_get_decals(CullTraverserData &data, CullableObject *decals) { if (node_effects->has_show_bounds()) { // If we should show the bounding volume for this node, make it // up now. - show_bounds(data); + show_bounds(data, node_effects->has_show_tight_bounds()); } data.apply_transform_and_state(this); diff --git a/panda/src/pgraph/cullTraverser.h b/panda/src/pgraph/cullTraverser.h index 75afb074f9..d9d25a0a15 100644 --- a/panda/src/pgraph/cullTraverser.h +++ b/panda/src/pgraph/cullTraverser.h @@ -95,8 +95,9 @@ public: static PStatCollector _geoms_pcollector; private: - void show_bounds(CullTraverserData &data); + void show_bounds(CullTraverserData &data, bool tight); PT(Geom) make_bounds_viz(const BoundingVolume &vol); + PT(Geom) make_tight_bounds_viz(PandaNode *node); static Vertexf compute_point(const BoundingSphere *sphere, float latitude, float longitude); CPT(RenderState) get_bounds_outer_viz_state(); diff --git a/panda/src/pgraph/geomNode.cxx b/panda/src/pgraph/geomNode.cxx index e64924c52f..8149c5eab6 100644 --- a/panda/src/pgraph/geomNode.cxx +++ b/panda/src/pgraph/geomNode.cxx @@ -358,7 +358,7 @@ calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, bool &found_any, const qpGeom *qpgeom = DCAST(qpGeom, geom); qpgeom->calc_tight_bounds(min_point, max_point, found_any, qpgeom->get_vertex_data()->animate_vertices(), - !transform->is_identity(), mat); + !next_transform->is_identity(), mat); } else { Geom::VertexIterator vi = geom->make_vertex_iterator(); diff --git a/panda/src/pgraph/nodePath.cxx b/panda/src/pgraph/nodePath.cxx index a0f61cc250..1c1df9e251 100644 --- a/panda/src/pgraph/nodePath.cxx +++ b/panda/src/pgraph/nodePath.cxx @@ -4710,7 +4710,23 @@ prepare_scene(GraphicsStateGuardianBase *gsg) { void NodePath:: show_bounds() { nassertv_always(!is_empty()); - node()->set_effect(ShowBoundsEffect::make()); + node()->set_effect(ShowBoundsEffect::make(false)); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::show_tight_bounds +// Access: Published +// Description: Similar to show_bounds(), this draws a bounding box +// representing the "tight" bounds of this node and all +// of its descendants. The bounding box is recomputed +// every frame by reexamining all of the vertices; this +// is far from efficient, but this is intended for +// debugging. +//////////////////////////////////////////////////////////////////// +void NodePath:: +show_tight_bounds() { + nassertv_always(!is_empty()); + node()->set_effect(ShowBoundsEffect::make(true)); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgraph/nodePath.h b/panda/src/pgraph/nodePath.h index 27b0aec7dd..26b8f9bae5 100644 --- a/panda/src/pgraph/nodePath.h +++ b/panda/src/pgraph/nodePath.h @@ -703,6 +703,7 @@ PUBLISHED: void prepare_scene(GraphicsStateGuardianBase *gsg); void show_bounds(); + void show_tight_bounds(); void hide_bounds(); PT(BoundingVolume) get_bounds() const; void force_recompute_bounds(); diff --git a/panda/src/pgraph/renderEffects.I b/panda/src/pgraph/renderEffects.I index 09c3a4da17..2e7ef47982 100644 --- a/panda/src/pgraph/renderEffects.I +++ b/panda/src/pgraph/renderEffects.I @@ -183,6 +183,23 @@ has_show_bounds() const { return ((_flags & F_has_show_bounds) != 0); } +//////////////////////////////////////////////////////////////////// +// Function: RenderEffects::has_show_tight_bounds +// Access: Public +// Description: If has_show_bounds() returns true, this will return +// true if the ShowBoundsEffect in question requests +// showing a "tight" bound. +//////////////////////////////////////////////////////////////////// +INLINE bool RenderEffects:: +has_show_tight_bounds() const { + if ((_flags & F_checked_show_bounds) == 0) { + // We pretend this function is const, even though it transparently + // modifies the internal show_bounds cache. + ((RenderEffects *)this)->determine_show_bounds(); + } + return ((_flags & F_has_show_tight_bounds) != 0); +} + //////////////////////////////////////////////////////////////////// // Function: RenderEffects::has_cull_callback // Access: Public diff --git a/panda/src/pgraph/renderEffects.cxx b/panda/src/pgraph/renderEffects.cxx index fe7847f68b..35a0c3c1d6 100644 --- a/panda/src/pgraph/renderEffects.cxx +++ b/panda/src/pgraph/renderEffects.cxx @@ -592,6 +592,10 @@ determine_show_bounds() { const RenderEffect *effect = get_effect(ShowBoundsEffect::get_class_type()); if (effect != (const RenderEffect *)NULL) { _flags |= F_has_show_bounds; + const ShowBoundsEffect *sba = DCAST(ShowBoundsEffect, effect); + if (sba->get_tight()) { + _flags |= F_has_show_tight_bounds; + } } _flags |= F_checked_show_bounds; } diff --git a/panda/src/pgraph/renderEffects.h b/panda/src/pgraph/renderEffects.h index 9ba914c222..0291ddcbdb 100644 --- a/panda/src/pgraph/renderEffects.h +++ b/panda/src/pgraph/renderEffects.h @@ -97,6 +97,7 @@ PUBLISHED: public: INLINE bool has_decal() const; INLINE bool has_show_bounds() const; + INLINE bool has_show_tight_bounds() const; INLINE bool has_cull_callback() const; void cull_callback(CullTraverser *trav, CullTraverserData &data, @@ -148,10 +149,11 @@ private: F_has_decal = 0x0002, F_checked_show_bounds = 0x0004, F_has_show_bounds = 0x0008, - F_checked_cull_callback = 0x0010, - F_has_cull_callback = 0x0020, - F_checked_adjust_transform = 0x0040, - F_has_adjust_transform = 0x0080, + F_has_show_tight_bounds = 0x0010, + F_checked_cull_callback = 0x0020, + F_has_cull_callback = 0x0040, + F_checked_adjust_transform = 0x0080, + F_has_adjust_transform = 0x0100, }; int _flags; diff --git a/panda/src/pgraph/showBoundsEffect.I b/panda/src/pgraph/showBoundsEffect.I index 2142ab8576..7a8775b557 100644 --- a/panda/src/pgraph/showBoundsEffect.I +++ b/panda/src/pgraph/showBoundsEffect.I @@ -24,5 +24,19 @@ // ShowBoundsEffect object. //////////////////////////////////////////////////////////////////// INLINE ShowBoundsEffect:: -ShowBoundsEffect() { +ShowBoundsEffect() : + _tight(false) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: ShowBoundsEffect::get_tight +// Access: Published +// Description: Returns true if the "tight" flag was set, meaning the +// effect should compute and draw the tight bounding-box +// of the node's vertices every frame. +//////////////////////////////////////////////////////////////////// +INLINE bool ShowBoundsEffect:: +get_tight() const { + return _tight; } diff --git a/panda/src/pgraph/showBoundsEffect.cxx b/panda/src/pgraph/showBoundsEffect.cxx index 438213bce8..b236592ab1 100644 --- a/panda/src/pgraph/showBoundsEffect.cxx +++ b/panda/src/pgraph/showBoundsEffect.cxx @@ -30,8 +30,9 @@ TypeHandle ShowBoundsEffect::_type_handle; // Description: Constructs a new ShowBoundsEffect object. //////////////////////////////////////////////////////////////////// CPT(RenderEffect) ShowBoundsEffect:: -make() { +make(bool tight) { ShowBoundsEffect *effect = new ShowBoundsEffect; + effect->_tight = tight; return return_new(effect); } @@ -64,25 +65,10 @@ safe_to_combine() const { //////////////////////////////////////////////////////////////////// int ShowBoundsEffect:: compare_to_impl(const RenderEffect *other) const { - // All ShowBoundsEffects are equivalent--there are no properties to - // store. - return 0; -} + const ShowBoundsEffect *ta; + DCAST_INTO_R(ta, other, 0); -//////////////////////////////////////////////////////////////////// -// Function: ShowBoundsEffect::make_default_impl -// Access: Protected, Virtual -// Description: Intended to be overridden by derived ShowBoundsEffect -// types to specify what the default property for a -// ShowBoundsEffect of this type should be. -// -// This should return a newly-allocated ShowBoundsEffect of -// the same type that corresponds to whatever the -// standard default for this kind of ShowBoundsEffect is. -//////////////////////////////////////////////////////////////////// -RenderEffect *ShowBoundsEffect:: -make_default_impl() const { - return new ShowBoundsEffect; + return (int)_tight - (int)ta->_tight; } //////////////////////////////////////////////////////////////////// @@ -105,6 +91,7 @@ register_with_read_factory() { void ShowBoundsEffect:: write_datagram(BamWriter *manager, Datagram &dg) { RenderEffect::write_datagram(manager, dg); + dg.add_bool(_tight); } //////////////////////////////////////////////////////////////////// @@ -137,4 +124,5 @@ make_from_bam(const FactoryParams ¶ms) { void ShowBoundsEffect:: fillin(DatagramIterator &scan, BamReader *manager) { RenderEffect::fillin(scan, manager); + _tight = scan.get_bool(); } diff --git a/panda/src/pgraph/showBoundsEffect.h b/panda/src/pgraph/showBoundsEffect.h index c9fb936f9b..3c9549e674 100644 --- a/panda/src/pgraph/showBoundsEffect.h +++ b/panda/src/pgraph/showBoundsEffect.h @@ -37,12 +37,16 @@ private: INLINE ShowBoundsEffect(); PUBLISHED: - static CPT(RenderEffect) make(); + static CPT(RenderEffect) make(bool tight = false); + + INLINE bool get_tight() const; protected: virtual bool safe_to_combine() const; virtual int compare_to_impl(const RenderEffect *other) const; - virtual RenderEffect *make_default_impl() const; + +private: + bool _tight; public: static void register_with_read_factory();