Explorar el Código

fix calc_tight_bounds(), add NodePath::show_tight_bounds()

David Rose hace 20 años
padre
commit
5e8855ebc8

+ 4 - 4
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]),

+ 92 - 16
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);
-
-    CullableObject *inner_viz = 
-      new CullableObject(bounds_viz, get_bounds_inner_viz_state(), 
-                         data._render_transform);
-    _cull_handler->record_object(inner_viz, this);
+  if (tight) {
+    PT(Geom) bounds_viz = make_tight_bounds_viz(node);
+
+    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);

+ 2 - 1
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();

+ 1 - 1
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();

+ 17 - 1
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));
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 0
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();

+ 17 - 0
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

+ 4 - 0
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;
 }

+ 6 - 4
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;
 

+ 15 - 1
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;
 }

+ 7 - 19
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 &params) {
 void ShowBoundsEffect::
 fillin(DatagramIterator &scan, BamReader *manager) {
   RenderEffect::fillin(scan, manager);
+  _tight = scan.get_bool();
 }

+ 6 - 2
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();