David Rose 23 tahun lalu
induk
melakukan
0be100989d

+ 55 - 6
panda/src/parametrics/nurbsCurveEvaluator.cxx

@@ -111,6 +111,17 @@ set_vertex(int i, const LVecBase4f &vertex) {
   _vertices[i].set_vertex(vertex);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsCurveEvaluator::set_vertex
+//       Access: Published
+//  Description: Sets the nth control vertex of the curve.
+////////////////////////////////////////////////////////////////////
+void NurbsCurveEvaluator::
+set_vertex(int i, const LVecBase3f &vertex, float weight) {
+  nassertv(i >= 0 && i < (int)_vertices.size());
+  _vertices[i].set_vertex(LVecBase4f(vertex[0] * weight, vertex[1] * weight, vertex[2] * weight, weight));
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: NurbsCurveEvaluator::get_vertex
 //       Access: Published
@@ -203,15 +214,32 @@ get_knot(int i) const {
 //               indicated coordinate space.
 ////////////////////////////////////////////////////////////////////
 PT(NurbsCurveResult) NurbsCurveEvaluator::
-evaluate(const NodePath &rel_to) {
+evaluate(const NodePath &rel_to) const {
   if (_basis_dirty) {
     ((NurbsCurveEvaluator *)this)->recompute_basis();
   }
 
   // First, transform the vertices as appropriate.
-  int num_vertices = (int)_vertices.size();
   pvector<LVecBase4f> verts;
-  verts.reserve(num_vertices);
+  get_vertices(verts, rel_to);
+
+  // And apply those transformed vertices to the basis matrices to
+  // derive the result.
+  return new NurbsCurveResult(_basis, _order, &verts[0], (int)verts.size());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsCurveEvaluator::get_vertices
+//       Access: Public
+//  Description: Fills the indicated vector with the set of vertices
+//               in the curve, transformed to the given space.  This
+//               flavor returns the vertices in 4-dimensional
+//               homogenous space.
+////////////////////////////////////////////////////////////////////
+void NurbsCurveEvaluator::
+get_vertices(pvector<LVecBase4f> &verts, const NodePath &rel_to) const {
+  int num_vertices = (int)_vertices.size();
+  verts.reserve(verts.size() + num_vertices);
   int vi;
   for (vi = 0; vi < num_vertices; vi++) {
     const NodePath &space = _vertices[vi].get_space();
@@ -223,10 +251,31 @@ evaluate(const NodePath &rel_to) {
       verts.push_back(vertex * mat);
     }
   }
+}
 
-  // And apply those transformed vertices to the basis matrices to
-  // derive the result.
-  return new NurbsCurveResult(_basis, _order, &verts[0], num_vertices);
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsCurveEvaluator::get_vertices
+//       Access: Public
+//  Description: Fills the indicated vector with the set of vertices
+//               in the curve, transformed to the given space.  This
+//               flavor returns the vertices in 4-dimensional
+//               homogenous space.
+////////////////////////////////////////////////////////////////////
+void NurbsCurveEvaluator::
+get_vertices(pvector<LPoint3f> &verts, const NodePath &rel_to) const {
+  int num_vertices = (int)_vertices.size();
+  verts.reserve(verts.size() + num_vertices);
+  int vi;
+  for (vi = 0; vi < num_vertices; vi++) {
+    const NodePath &space = _vertices[vi].get_space();
+    LVecBase4f vertex = _vertices[vi].get_vertex();
+    if (!space.is_empty()) {
+      const LMatrix4f &mat = space.get_mat(rel_to);
+      vertex = vertex * mat;
+    }
+    LPoint3f v3(vertex[0] / vertex[3], vertex[1] / vertex[3], vertex[2] / vertex[3]);
+    verts.push_back(v3);
+  }
 }
 
 ////////////////////////////////////////////////////////////////////

+ 7 - 1
panda/src/parametrics/nurbsCurveEvaluator.h

@@ -28,6 +28,7 @@
 #include "pvector.h"
 #include "nodePath.h"
 #include "referenceCount.h"
+#include "luse.h"
 
 ////////////////////////////////////////////////////////////////////
 //       Class : NurbsCurveEvaluator
@@ -56,6 +57,7 @@ PUBLISHED:
 
   int get_num_vertices() const;
   void set_vertex(int i, const LVecBase4f &vertex);
+  void set_vertex(int i, const LVecBase3f &vertex, float weight = 1.0);
   const LVecBase4f &get_vertex(int i) const;
 
   void set_vertex_space(int i, const NodePath &space);
@@ -65,7 +67,11 @@ PUBLISHED:
   void set_knot(int i, float knot);
   float get_knot(int i) const;
 
-  PT(NurbsCurveResult) evaluate(const NodePath &rel_to = NodePath());
+  PT(NurbsCurveResult) evaluate(const NodePath &rel_to = NodePath()) const;
+
+public:
+  void get_vertices(pvector<LVecBase4f> &verts, const NodePath &rel_to) const;
+  void get_vertices(pvector<LPoint3f> &verts, const NodePath &rel_to) const;
 
 private:
   void recompute_knots();

+ 1 - 1
panda/src/parametrics/nurbsCurveResult.I

@@ -55,7 +55,7 @@ get_end_t() const {
 //               the t value is value, false otherwise.
 ////////////////////////////////////////////////////////////////////
 INLINE bool NurbsCurveResult::
-eval_point(float t, LPoint3f &point) {
+eval_point(float t, LVecBase3f &point) {
   int segment = find_segment(t);
   if (segment == -1) {
     return false;

+ 1 - 1
panda/src/parametrics/nurbsCurveResult.cxx

@@ -73,7 +73,7 @@ NurbsCurveResult(const NurbsMatrixVector &basis, int order,
 //               evaluate the points along each segment.
 ////////////////////////////////////////////////////////////////////
 void NurbsCurveResult::
-eval_segment_point(int segment, float t, LPoint3f &point) const {
+eval_segment_point(int segment, float t, LVecBase3f &point) const {
   const LMatrix4f &mat = _prod.get_matrix(segment);
 
   float t2 = t*t;

+ 2 - 2
panda/src/parametrics/nurbsCurveResult.h

@@ -48,10 +48,10 @@ PUBLISHED:
   INLINE float get_start_t() const;
   INLINE float get_end_t() const;
 
-  INLINE bool eval_point(float t, LPoint3f &point);
+  INLINE bool eval_point(float t, LVecBase3f &point);
   
   INLINE int get_num_segments() const;
-  void eval_segment_point(int segment, float t, LPoint3f &point) const;
+  void eval_segment_point(int segment, float t, LVecBase3f &point) const;
   
 private:
   int find_segment(float t);

+ 1 - 0
panda/src/parametrics/ropeNode.I

@@ -71,6 +71,7 @@ get_curve() const {
 ////////////////////////////////////////////////////////////////////
 INLINE void RopeNode::
 set_num_segs(int num_segs) {
+  nassertv(num_segs >= 0);
   CDWriter cdata(_cycler);
   cdata->_num_segs = num_segs;
 }

+ 66 - 26
panda/src/parametrics/ropeNode.cxx

@@ -21,6 +21,7 @@
 #include "cullTraverserData.h"
 #include "cullableObject.h"
 #include "cullHandler.h"
+#include "geomLinestrip.h"
 #include "bamWriter.h"
 #include "bamReader.h"
 #include "datagram.h"
@@ -148,37 +149,37 @@ has_cull_callback() const {
 ////////////////////////////////////////////////////////////////////
 bool RopeNode::
 cull_callback(CullTraverser *trav, CullTraverserData &data) {
-  cerr << "cull_callback\n";
-
   // Create a new linestrip on-the-fly to render the rope.
-  PT(Geom) geom = new GeomLinestrip;
-  PTA_Vertexf verts;
-  PTA_int lengths;
+  int num_verts = get_num_segs() + 1;
+  if (num_verts >= 2) {
+    PTA_Vertexf verts;
+    PTA_int lengths;
 
-  NurbsCurveEvaluator *curve = get_curve();
-  PT(NurbsCurveResult) result = curve->evaluate(data._node_path.get_node_path());
+    NurbsCurveEvaluator *curve = get_curve();
+    PT(NurbsCurveResult) result = curve->evaluate(data._node_path.get_node_path());
 
-  int num_segments = result->get_num_segments();
-  int num_segs = get_num_segs();
-  for (int segment = 0; segment < num_segments; segment++) {
-    cerr << "\nsegment " << segment << "\n";
-    for (int i = 0; i < num_segs; i++) {
-      float t = (float)i / (float)(num_segs - 1);
-      LPoint3f point;
-      result->eval_segment_point(segment, t, point);
-      verts.push_back(point);
-      cerr << "  p " << point << "\n";
+    int num_segments = result->get_num_segments();
+    if (num_segments > 0) {
+      for (int segment = 0; segment < num_segments; segment++) {
+        for (int i = 0; i < num_verts; i++) {
+          float t = (float)i / (float)(num_verts - 1);
+          LPoint3f point;
+          result->eval_segment_point(segment, t, point);
+          verts.push_back(point);
+        }
+        lengths.push_back(num_verts);
+      }
+      
+      PT(Geom) geom = new GeomLinestrip;
+      geom->set_num_prims(num_segments);
+      geom->set_coords(verts);
+      geom->set_lengths(lengths);
+      
+      CullableObject *object = new CullableObject(geom, data._state,
+                                                  data._render_transform);
+      trav->get_cull_handler()->record_object(object);
     }
-    lengths.push_back(num_segs);
   }
-
-  geom->set_num_prims(num_segments);
-  geom->set_coords(verts);
-  geom->set_lengths(lengths);
-
-  CullableObject *object = new CullableObject(geom, data._state,
-                                              data._render_transform);
-  trav->get_cull_handler()->record_object(object);
   
   return true;
 }
@@ -205,6 +206,45 @@ write(ostream &out, int indent_level) const {
   indent(out, indent_level) << get_curve() << "\n";
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: RopeNode::reset_bound
+//       Access: Published
+//  Description: Recomputes the bounding volume.  This is normally
+//               called automatically, but it must occasionally be
+//               called explicitly when the curve has changed
+//               properties outside of this node's knowledge.
+////////////////////////////////////////////////////////////////////
+BoundingVolume *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;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RopeNode::recompute_internal_bound
+//       Access: Protected, Virtual
+//  Description: Called when needed to recompute the node's
+//               _internal_bound object.  Nodes that contain anything
+//               of substance should redefine this to do the right
+//               thing.
+////////////////////////////////////////////////////////////////////
+BoundingVolume *RopeNode::
+recompute_internal_bound() {
+  return reset_bound(NodePath(this));
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: RopeNode::register_with_read_factory
 //       Access: Public, Static

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

@@ -58,7 +58,11 @@ PUBLISHED:
 
   INLINE void set_num_segs(int num_segs);
   INLINE int get_num_segs() const;
-  
+
+  BoundingVolume *reset_bound(const NodePath &rel_to);
+
+protected:
+  virtual BoundingVolume *recompute_internal_bound();
 
 private:
   // This is the data that must be cycled between pipeline stages.