Browse Source

early pass on RopeNode

David Rose 23 years ago
parent
commit
e7aae0ca54

+ 5 - 2
panda/src/parametrics/Sources.pp

@@ -24,6 +24,7 @@
     parametricCurve.h  \
     parametricCurveCollection.I parametricCurveCollection.h  \
     piecewiseCurve.h \
+    ropeNode.I ropeNode.h \
     $[if $[HAVE_NURBSPP], nurbsPPCurve.cxx nurbsPPCurve.h]
 
 
@@ -37,7 +38,8 @@
     nurbsMatrixVector.cxx \
     nurbsVertex.cxx \
     parametricCurve.cxx parametricCurveCollection.cxx  \
-    piecewiseCurve.cxx 
+    piecewiseCurve.cxx \
+    ropeNode.cxx
 
   #define INSTALL_HEADERS \
     classicNurbsCurve.I classicNurbsCurve.h \
@@ -56,7 +58,8 @@
     nurbsPPCurve.h \
     parametricCurve.h \
     parametricCurveCollection.I parametricCurveCollection.h \
-    piecewiseCurve.h
+    piecewiseCurve.h \
+    ropeNode.I ropeNode.h
 
   #define IGATESCAN all
 

+ 3 - 0
panda/src/parametrics/config_parametrics.cxx

@@ -26,6 +26,7 @@
 #include "parametricCurve.h"
 #include "parametricCurveDrawer.h"
 #include "piecewiseCurve.h"
+#include "ropeNode.h"
 
 #ifdef HAVE_NURBSPP
 #include "nurbsPPCurve.h"
@@ -46,6 +47,7 @@ ConfigureFn(config_parametrics) {
   ParametricCurve::init_type();
   ParametricCurveDrawer::init_type();
   PiecewiseCurve::init_type();
+  RopeNode::init_type();
 
 #ifdef HAVE_NURBSPP
   NurbsPPCurve::init_type();
@@ -55,6 +57,7 @@ ConfigureFn(config_parametrics) {
   ClassicNurbsCurve::register_with_read_factory();
   CubicCurveseg::register_with_read_factory();
   HermiteCurve::register_with_read_factory();
+  RopeNode::register_with_read_factory();
 }
 
 const DSearchPath &

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

@@ -27,6 +27,7 @@
 #include "vector_float.h"
 #include "pvector.h"
 #include "nodePath.h"
+#include "referenceCount.h"
 
 ////////////////////////////////////////////////////////////////////
 //       Class : NurbsCurveEvaluator
@@ -43,7 +44,7 @@
 //               eventually replace the whole ParametricCurve class
 //               hierarchy.
 ////////////////////////////////////////////////////////////////////
-class EXPCL_PANDA NurbsCurveEvaluator {
+class EXPCL_PANDA NurbsCurveEvaluator : public ReferenceCount {
 PUBLISHED:
   NurbsCurveEvaluator();
   ~NurbsCurveEvaluator();

+ 40 - 0
panda/src/parametrics/nurbsCurveResult.I

@@ -17,6 +17,15 @@
 ////////////////////////////////////////////////////////////////////
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsCurveResult::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE NurbsCurveResult::
+~NurbsCurveResult() {
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: NurbsCurveResult::get_start_t
 //       Access: Public
@@ -37,3 +46,34 @@ INLINE float NurbsCurveResult::
 get_end_t() const {
   return _prod.get_end_t();
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsCurveResult::eval_point
+//       Access: Published
+//  Description: Computes the point on the curve corresponding to the
+//               indicated value in parametric time.  Returns true if
+//               the t value is value, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool NurbsCurveResult::
+eval_point(float t, LPoint3f &point) {
+  int segment = find_segment(t);
+  if (segment == -1) {
+    return false;
+  }
+
+  eval_segment_point(segment, _prod.scale_t(segment, t), point);
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsCurveResult::get_num_segments
+//       Access: Public
+//  Description: Returns the number of piecewise continuous segments
+//               within the curve.  This number is usually not
+//               important unless you plan to call
+//               eval_segment_point().
+////////////////////////////////////////////////////////////////////
+INLINE int NurbsCurveResult::
+get_num_segments() const {
+  return _prod.get_num_segments();
+}

+ 17 - 22
panda/src/parametrics/nurbsCurveResult.cxx

@@ -55,36 +55,31 @@ NurbsCurveResult(const NurbsMatrixVector &basis, int order,
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: NurbsCurveResult::Destructor
+//     Function: NurbsCurveResult::eval_segment_point
 //       Access: Published
-//  Description:
-////////////////////////////////////////////////////////////////////
-NurbsCurveResult::
-~NurbsCurveResult() {
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NurbsCurveResult::eval_point
-//       Access: Published
-//  Description: Computes the point on the curve corresponding to the
-//               indicated value in parametric time.  Returns true if
-//               the t value is value, false otherwise.
+//  Description: Evaluates the point on the curve corresponding to the
+//               indicated value in parametric time within the
+//               indicated curve segment.  t should be in the range
+//               [0, 1].
+//
+//               The curve is internally represented as a number of
+//               connected (or possibly unconnected) piecewise
+//               continuous segments.  The exact number of segments
+//               for a particular curve depends on the knot vector,
+//               and is returned by get_num_segments().  Normally,
+//               eval_point() is used to evaluate a point along the
+//               continuous curve, but when you care more about local
+//               continuity, you can use eval_segment_point() to
+//               evaluate the points along each segment.
 ////////////////////////////////////////////////////////////////////
-bool NurbsCurveResult::
-eval_point(float t, LPoint3f &point) {
-  int segment = find_segment(t);
-  if (segment == -1) {
-    return false;
-  }
-
-  t = _prod.scale_t(segment, t);
+void NurbsCurveResult::
+eval_segment_point(int segment, float t, LPoint3f &point) const {
   const LMatrix4f &mat = _prod.get_matrix(segment);
 
   float t2 = t*t;
   LVecBase4f tvec(t*t2, t2, t, 1.0f);
   LVecBase4f r = tvec * mat;
   point.set(r[0] / r[3], r[1] / r[3], r[2] / r[3]);
-  return true;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 5 - 4
panda/src/parametrics/nurbsCurveResult.h

@@ -43,12 +43,15 @@ public:
                    const LVecBase4f verts[], int num_vertices);
 
 PUBLISHED:
-  ~NurbsCurveResult();
+  INLINE ~NurbsCurveResult();
 
   INLINE float get_start_t() const;
   INLINE float get_end_t() const;
 
-  bool eval_point(float t, LPoint3f &point);
+  INLINE bool eval_point(float t, LPoint3f &point);
+  
+  INLINE int get_num_segments() const;
+  void eval_segment_point(int segment, float t, LPoint3f &point) const;
   
 private:
   int find_segment(float t);
@@ -59,8 +62,6 @@ private:
   int _last_segment;
   float _last_from;
   float _last_to;
-
-  friend class NurbsCurveEvaluator;
 };
 
 #include "nurbsCurveResult.I"

+ 1 - 0
panda/src/parametrics/parametrics_composite2.cxx

@@ -7,3 +7,4 @@
 #include "nurbsCurveResult.cxx"
 #include "nurbsMatrixVector.cxx"
 #include "nurbsVertex.cxx"
+#include "ropeNode.cxx"

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

@@ -0,0 +1,88 @@
+// Filename: ropeNode.I
+// Created by:  drose (04Dec02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: RopeNode::CData::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE RopeNode::CData::
+CData() {
+  _curve = new NurbsCurveEvaluator;
+  _num_segs = 10;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RopeNode::CData::Copy Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE RopeNode::CData::
+CData(const RopeNode::CData &copy) :
+  _curve(copy._curve)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: set_curve
+//       Access: Public
+//  Description: Sets the particular curve represented by the
+//               RopeNode.
+////////////////////////////////////////////////////////////////////
+INLINE void RopeNode::
+set_curve(NurbsCurveEvaluator *curve) {
+  CDWriter cdata(_cycler);
+  cdata->_curve = curve;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: get_curve
+//       Access: Public
+//  Description: Returns the curve represented by the RopeNode.
+////////////////////////////////////////////////////////////////////
+INLINE NurbsCurveEvaluator *RopeNode::
+get_curve() const {
+  CDReader cdata(_cycler);
+  return cdata->_curve;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: set_num_segs
+//       Access: Public
+//  Description: Specifies the number of segments per cubic segment
+//               (that is, per unique knot value) to draw in a fixed
+//               uniform tesselation of the curve.
+////////////////////////////////////////////////////////////////////
+INLINE void RopeNode::
+set_num_segs(int num_segs) {
+  CDWriter cdata(_cycler);
+  cdata->_num_segs = num_segs;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: get_num_segs
+//       Access: Public
+//  Description: Returns the number of segments per cubic segment to
+//               draw.  See set_num_segs().
+////////////////////////////////////////////////////////////////////
+INLINE int RopeNode::
+get_num_segs() const {
+  CDReader cdata(_cycler);
+  return cdata->_num_segs;
+}

+ 262 - 0
panda/src/parametrics/ropeNode.cxx

@@ -0,0 +1,262 @@
+// Filename: ropeNode.cxx
+// Created by:  drose (04Dec02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "ropeNode.h"
+#include "cullTraverser.h"
+#include "cullTraverserData.h"
+#include "cullableObject.h"
+#include "cullHandler.h"
+#include "bamWriter.h"
+#include "bamReader.h"
+#include "datagram.h"
+#include "datagramIterator.h"
+
+TypeHandle RopeNode::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: RopeNode::CData::make_copy
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+CycleData *RopeNode::CData::
+make_copy() const {
+  return new CData(*this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RopeNode::CData::write_datagram
+//       Access: Public, Virtual
+//  Description: Writes the contents of this object to the datagram
+//               for shipping out to a Bam file.
+////////////////////////////////////////////////////////////////////
+void RopeNode::CData::
+write_datagram(BamWriter *writer, Datagram &dg) const {
+  // For now, we write a NULL pointer.  Eventually we will write out
+  // the NurbsCurveEvaluator pointer.
+  writer->write_pointer(dg, (TypedWritable *)NULL);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RopeNode::CData::fillin
+//       Access: Public, Virtual
+//  Description: This internal function is called by make_from_bam to
+//               read in all of the relevant data from the BamFile for
+//               the new RopeNode.
+////////////////////////////////////////////////////////////////////
+void RopeNode::CData::
+fillin(DatagramIterator &scan, BamReader *reader) {
+  // For now, we skip over the NULL pointer that we wrote out.
+  reader->skip_pointer(scan);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RopeNode::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+RopeNode::
+RopeNode(const string &name) :
+  PandaNode(name)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RopeNode::Copy Constructor
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+RopeNode::
+RopeNode(const RopeNode &copy) :
+  PandaNode(copy),
+  _cycler(copy._cycler)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RopeNode::make_copy
+//       Access: Public, Virtual
+//  Description: Returns a newly-allocated Node that is a shallow copy
+//               of this one.  It will be a different Node pointer,
+//               but its internal data may or may not be shared with
+//               that of the original Node.
+////////////////////////////////////////////////////////////////////
+PandaNode *RopeNode::
+make_copy() const {
+  return new RopeNode(*this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RopeNode::safe_to_transform
+//       Access: Public, Virtual
+//  Description: Returns true if it is generally safe to transform
+//               this particular kind of Node by calling the xform()
+//               method, false otherwise.  For instance, it's usually
+//               a bad idea to attempt to xform a RopeNode.
+////////////////////////////////////////////////////////////////////
+bool RopeNode::
+safe_to_transform() const {
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RopeNode::has_cull_callback
+//       Access: Public, Virtual
+//  Description: Should be overridden by derived classes to return
+//               true if cull_callback() has been defined.  Otherwise,
+//               returns false to indicate cull_callback() does not
+//               need to be called for this node during the cull
+//               traversal.
+////////////////////////////////////////////////////////////////////
+bool RopeNode::
+has_cull_callback() const {
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RopeNode::cull_callback
+//       Access: Public, Virtual
+//  Description: If has_cull_callback() returns true, this function
+//               will be called during the cull traversal to perform
+//               any additional operations that should be performed at
+//               cull time.  This may include additional manipulation
+//               of render state or additional visible/invisible
+//               decisions, or any other arbitrary operation.
+//
+//               By the time this function is called, the node has
+//               already passed the bounding-volume test for the
+//               viewing frustum, and the node's transform and state
+//               have already been applied to the indicated
+//               CullTraverserData object.
+//
+//               The return value is true if this node should be
+//               visible, or false if it should be culled.
+////////////////////////////////////////////////////////////////////
+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;
+
+  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";
+    }
+    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;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RopeNode::output
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void RopeNode::
+output(ostream &out) const {
+  PandaNode::output(out);
+  out << " " << get_curve();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RopeNode::write
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void RopeNode::
+write(ostream &out, int indent_level) const {
+  PandaNode::write(out, indent_level);
+  indent(out, indent_level) << get_curve() << "\n";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RopeNode::register_with_read_factory
+//       Access: Public, Static
+//  Description: Tells the BamReader how to create objects of type
+//               RopeNode.
+////////////////////////////////////////////////////////////////////
+void RopeNode::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RopeNode::write_datagram
+//       Access: Public, Virtual
+//  Description: Writes the contents of this object to the datagram
+//               for shipping out to a Bam file.
+////////////////////////////////////////////////////////////////////
+void RopeNode::
+write_datagram(BamWriter *manager, Datagram &dg) {
+  PandaNode::write_datagram(manager, dg);
+  manager->write_cdata(dg, _cycler);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RopeNode::make_from_bam
+//       Access: Protected, Static
+//  Description: This function is called by the BamReader's factory
+//               when a new object of type RopeNode is encountered
+//               in the Bam file.  It should create the RopeNode
+//               and extract its information from the file.
+////////////////////////////////////////////////////////////////////
+TypedWritable *RopeNode::
+make_from_bam(const FactoryParams &params) {
+  RopeNode *node = new RopeNode("");
+  DatagramIterator scan;
+  BamReader *manager;
+
+  parse_params(params, scan, manager);
+  node->fillin(scan, manager);
+
+  return node;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RopeNode::fillin
+//       Access: Protected
+//  Description: This internal function is called by make_from_bam to
+//               read in all of the relevant data from the BamFile for
+//               the new RopeNode.
+////////////////////////////////////////////////////////////////////
+void RopeNode::
+fillin(DatagramIterator &scan, BamReader *manager) {
+  PandaNode::fillin(scan, manager);
+  manager->read_cdata(scan, _cycler);
+}

+ 109 - 0
panda/src/parametrics/ropeNode.h

@@ -0,0 +1,109 @@
+// Filename: ropeNode.h
+// Created by:  drose (04Dec02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef ROPENODE_H
+#define ROPENODE_H
+
+#include "pandabase.h"
+#include "nurbsCurveEvaluator.h"
+#include "pandaNode.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : RopeNode
+// Description : This class draws a visible representation of the
+//               NURBS curve stored in its NurbsCurveEvaluator.  It
+//               automatically recomputes the curve every frame.
+//
+//               This is not related to NurbsCurve, ClassicNurbsCurve,
+//               CubicCurveseg or any of the ParametricCurve-derived
+//               objects in this module.  It is a completely parallel
+//               implementation of NURBS curves, and will probably
+//               eventually replace the whole ParametricCurve class
+//               hierarchy.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA RopeNode : public PandaNode {
+PUBLISHED:
+  RopeNode(const string &name);
+
+protected:
+  RopeNode(const RopeNode &copy);
+public:
+  virtual void output(ostream &out) const;
+  virtual void write(ostream &out, int indent_level = 0) const;
+
+  virtual PandaNode *make_copy() const;
+
+  virtual bool safe_to_transform() const;
+  virtual bool has_cull_callback() const;
+  virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data);
+
+PUBLISHED:
+  INLINE void set_curve(NurbsCurveEvaluator *curve);
+  INLINE NurbsCurveEvaluator *get_curve() const;
+
+  INLINE void set_num_segs(int num_segs);
+  INLINE int get_num_segs() const;
+  
+
+private:
+  // This is the data that must be cycled between pipeline stages.
+  class EXPCL_PANDA CData : public CycleData {
+  public:
+    INLINE CData();
+    INLINE CData(const CData &copy);
+    virtual CycleData *make_copy() const;
+    virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
+    virtual void fillin(DatagramIterator &scan, BamReader *manager);
+
+    PT(NurbsCurveEvaluator) _curve;
+    int _num_segs;
+  };
+
+  PipelineCycler<CData> _cycler;
+  typedef CycleDataReader<CData> CDReader;
+  typedef CycleDataWriter<CData> CDWriter;
+
+public:
+  static void register_with_read_factory();
+  virtual void write_datagram(BamWriter *manager, Datagram &dg);
+
+protected:
+  static TypedWritable *make_from_bam(const FactoryParams &params);
+  void fillin(DatagramIterator &scan, BamReader *manager);
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    PandaNode::init_type();
+    register_type(_type_handle, "RopeNode",
+                  PandaNode::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "ropeNode.I"
+
+#endif