Bladeren bron

don't automatically recompute explicit bounding volumes

David Rose 23 jaren geleden
bovenliggende
commit
673c162389

+ 35 - 16
panda/src/parametrics/ropeNode.cxx

@@ -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,

+ 21 - 1
panda/src/parametrics/ropeNode.h

@@ -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, 

+ 1 - 38
panda/src/pgraph/nodePath.cxx

@@ -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

+ 0 - 1
panda/src/pgraph/nodePath.h

@@ -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,

+ 6 - 0
panda/src/pgraph/nodePathComponent.I

@@ -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;
+}
+

+ 37 - 0
panda/src/pgraph/nodePathComponent.cxx

@@ -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

+ 4 - 0
panda/src/pgraph/nodePathComponent.h

@@ -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

+ 10 - 2
panda/src/pgraph/pandaNode.I

@@ -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();

+ 26 - 4
panda/src/pgraph/pandaNode.cxx

@@ -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;

+ 3 - 0
panda/src/pgraph/pandaNode.h

@@ -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;