소스 검색

first pass at NurbsCurveEvaluator

David Rose 23 년 전
부모
커밋
340d20717e

+ 28 - 14
panda/src/parametrics/Sources.pp

@@ -11,23 +11,33 @@
   #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx    
 
   #define SOURCES \
-     classicNurbsCurve.I classicNurbsCurve.h config_parametrics.h  \
-     cubicCurveseg.h parametricCurveDrawer.I  \
-     parametricCurveDrawer.h curveFitter.I curveFitter.h  \
-     hermiteCurve.h nurbsCurve.h nurbsCurveDrawer.I  \
-     nurbsCurveDrawer.h nurbsCurveInterface.I  \
-     nurbsCurveInterface.h parametricCurve.h  \
-     parametricCurveCollection.I parametricCurveCollection.h  \
-     piecewiseCurve.h \
-     $[if $[HAVE_NURBSPP], nurbsPPCurve.cxx nurbsPPCurve.h]
+    classicNurbsCurve.I classicNurbsCurve.h config_parametrics.h  \
+    cubicCurveseg.h parametricCurveDrawer.I  \
+    parametricCurveDrawer.h curveFitter.I curveFitter.h  \
+    hermiteCurve.h nurbsCurve.h \
+    nurbsCurveDrawer.I nurbsCurveDrawer.h \
+    nurbsCurveEvaluator.h \
+    nurbsCurveInterface.I nurbsCurveInterface.h \
+    nurbsCurveResult.I nurbsCurveResult.h \
+    nurbsMatrixVector.I nurbsMatrixVector.h \
+    nurbsVertex.h nurbsVertex.I \
+    parametricCurve.h  \
+    parametricCurveCollection.I parametricCurveCollection.h  \
+    piecewiseCurve.h \
+    $[if $[HAVE_NURBSPP], nurbsPPCurve.cxx nurbsPPCurve.h]
 
 
   #define INCLUDED_SOURCES \
-     classicNurbsCurve.cxx config_parametrics.cxx cubicCurveseg.cxx  \
-     parametricCurveDrawer.cxx curveFitter.cxx hermiteCurve.cxx  \
-     nurbsCurveDrawer.cxx nurbsCurveInterface.cxx  \
-     parametricCurve.cxx parametricCurveCollection.cxx  \
-     piecewiseCurve.cxx 
+    classicNurbsCurve.cxx config_parametrics.cxx cubicCurveseg.cxx  \
+    parametricCurveDrawer.cxx curveFitter.cxx hermiteCurve.cxx  \
+    nurbsCurveDrawer.cxx \
+    nurbsCurveEvaluator.cxx \
+    nurbsCurveResult.cxx \
+    nurbsCurveInterface.cxx  \
+    nurbsMatrixVector.cxx \
+    nurbsVertex.cxx \
+    parametricCurve.cxx parametricCurveCollection.cxx  \
+    piecewiseCurve.cxx 
 
   #define INSTALL_HEADERS \
     classicNurbsCurve.I classicNurbsCurve.h \
@@ -38,7 +48,11 @@
     hermiteCurve.h \
     nurbsCurve.h \
     nurbsCurveDrawer.I nurbsCurveDrawer.h \
+    nurbsCurveEvaluator.h \
     nurbsCurveInterface.I nurbsCurveInterface.h \
+    nurbsCurveResult.I nurbsCurveResult.h \
+    nurbsMatrixVector.I nurbsMatrixVector.h \
+    nurbsVertex.h nurbsVertex.I \
     nurbsPPCurve.h \
     parametricCurve.h \
     parametricCurveCollection.I parametricCurveCollection.h \

+ 291 - 0
panda/src/parametrics/nurbsCurveEvaluator.cxx

@@ -0,0 +1,291 @@
+// Filename: nurbsCurveEvaluator.cxx
+// Created by:  drose (03Dec02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "nurbsCurveEvaluator.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsCurveEvaluator::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+NurbsCurveEvaluator::
+NurbsCurveEvaluator() {
+  _order = 4;
+  _knots_dirty = true;
+  _basis_dirty = true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsCurveEvaluator::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+NurbsCurveEvaluator::
+~NurbsCurveEvaluator() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsCurveEvaluator::set_order
+//       Access: Published
+//  Description: Sets the order of the curve.  This resets the knot
+//               vector to the default knot vector for the number of
+//               vertices.
+//
+//               The order must be 1, 2, 3, or 4, and the value is one
+//               more than the degree of the curve.
+////////////////////////////////////////////////////////////////////
+void NurbsCurveEvaluator::
+set_order(int order) {
+  _order = order;
+  _knots_dirty = true;
+  _basis_dirty = true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsCurveEvaluator::get_order
+//       Access: Published
+//  Description: Returns the order of the curve as set by a previous
+//               call to set_order().
+////////////////////////////////////////////////////////////////////
+int NurbsCurveEvaluator::
+get_order() const {
+  return _order;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsCurveEvaluator::reset
+//       Access: Published
+//  Description: Resets all the vertices and knots to their default
+//               values, and sets the curve up with the indicated
+//               number of vertices.  You must then call set_vertex()
+//               repeatedly to fill in all of the vertex values
+//               appropriately.
+////////////////////////////////////////////////////////////////////
+void NurbsCurveEvaluator::
+reset(int num_vertices) {
+  _vertices.clear();
+  _vertices.reserve(num_vertices);
+
+  for (int i = 0; i < num_vertices; i++) {
+    _vertices.push_back(NurbsVertex());
+  }
+  _knots_dirty = true;
+  _basis_dirty = true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsCurveEvaluator::get_num_vertices
+//       Access: Published
+//  Description: Returns the number of control vertices in the curve.
+//               This is the number passed to the last call to
+//               reset().
+////////////////////////////////////////////////////////////////////
+int NurbsCurveEvaluator::
+get_num_vertices() const {
+  return (int)_vertices.size();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsCurveEvaluator::set_vertex
+//       Access: Published
+//  Description: Sets the nth control vertex of the curve.
+////////////////////////////////////////////////////////////////////
+void NurbsCurveEvaluator::
+set_vertex(int i, const LVecBase4f &vertex) {
+  nassertv(i >= 0 && i < (int)_vertices.size());
+  _vertices[i].set_vertex(vertex);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsCurveEvaluator::get_vertex
+//       Access: Published
+//  Description: Returns the nth control vertex of the curve, relative
+//               to its indicated coordinate space.
+////////////////////////////////////////////////////////////////////
+const LVecBase4f &NurbsCurveEvaluator::
+get_vertex(int i) const {
+  nassertr(i >= 0 && i < (int)_vertices.size(), LVecBase4f::zero());
+  return _vertices[i].get_vertex();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsCurveEvaluator::set_vertex_space
+//       Access: Published
+//  Description: Sets the coordinate space of the nth control vertex.
+//               If this is not specified, or is set to an empty
+//               NodePath, the nth control vertex is deemed to be in
+//               the coordinate space passed to evaluate().
+////////////////////////////////////////////////////////////////////
+void NurbsCurveEvaluator::
+set_vertex_space(int i, const NodePath &space) {
+  nassertv(i >= 0 && i < (int)_vertices.size());
+  _vertices[i].set_space(space);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsCurveEvaluator::get_vertex_space
+//       Access: Published
+//  Description: Returns the coordinate space of the nth control
+//               vertex of the curve, expressed as a NodePath.
+////////////////////////////////////////////////////////////////////
+const NodePath &NurbsCurveEvaluator::
+get_vertex_space(int i) const {
+#ifndef NDEBUG
+  static NodePath empty_node_path;
+  nassertr(i >= 0 && i < (int)_vertices.size(), empty_node_path);
+#endif
+  return _vertices[i].get_space();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsCurveEvaluator::get_num_knots
+//       Access: Published
+//  Description: Returns the number of knot values in the curve.  This
+//               is based on the number of vertices and the order.
+////////////////////////////////////////////////////////////////////
+int NurbsCurveEvaluator::
+get_num_knots() const {
+  return (int)_vertices.size() + _order;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsCurveEvaluator::set_knot
+//       Access: Published
+//  Description: Sets the value of the nth knot.  Each knot value
+//               should be greater than or equal to the preceding
+//               value.  If no knot values are set, a default knot
+//               vector is supplied.
+////////////////////////////////////////////////////////////////////
+void NurbsCurveEvaluator::
+set_knot(int i, float knot) {
+  if (_knots_dirty) {
+    recompute_knots();
+  }
+  nassertv(i >= 0 && i < (int)_knots.size());
+  _knots[i] = knot;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsCurveEvaluator::get_knot
+//       Access: Published
+//  Description: Returns the value of the nth knot.
+////////////////////////////////////////////////////////////////////
+float NurbsCurveEvaluator::
+get_knot(int i) const {
+  if (_knots_dirty) {
+    ((NurbsCurveEvaluator *)this)->recompute_knots();
+  }
+  nassertr(i >= 0 && i < (int)_knots.size(), 0.0f);
+  return _knots[i];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsCurveEvaluator::evaluate
+//       Access: Published
+//  Description: Returns a NurbsCurveResult object that represents the
+//               result of applying the knots to all of the current
+//               values of the vertices, transformed into the
+//               indicated coordinate space.
+////////////////////////////////////////////////////////////////////
+PT(NurbsCurveResult) NurbsCurveEvaluator::
+evaluate(const NodePath &rel_to) {
+  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);
+  int vi;
+  for (vi = 0; vi < num_vertices; vi++) {
+    const NodePath &space = _vertices[vi].get_space();
+    const LVecBase4f &vertex = _vertices[vi].get_vertex();
+    if (space.is_empty()) {
+      verts.push_back(vertex);
+    } else {
+      const LMatrix4f &mat = space.get_mat(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::recompute_knots
+//       Access: Private
+//  Description: Creates a default knot vector.
+////////////////////////////////////////////////////////////////////
+void NurbsCurveEvaluator::
+recompute_knots() {
+  _knots.clear();
+  int num_knots = get_num_knots();
+  _knots.reserve(num_knots);
+
+  float value = 0.0f;
+
+  int i = 0;
+  while (i < _order) {
+    _knots.push_back(value);
+    i++;
+  }
+  while (i < num_knots - _order) {
+    value += 1.0f;
+    _knots.push_back(value);
+    i++;
+  }
+  value += 1.0f;
+  while (i < num_knots) {
+    _knots.push_back(value);
+    i++;
+  }
+
+  _knots_dirty = false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsCurveEvaluator::recompute_basis
+//       Access: Private
+//  Description: Recomputes the basis matrices according to the knot
+//               vector.
+////////////////////////////////////////////////////////////////////
+void NurbsCurveEvaluator::
+recompute_basis() {
+  if (_knots_dirty) {
+    ((NurbsCurveEvaluator *)this)->recompute_knots();
+  }
+
+  _basis.clear();
+  if ((int)_vertices.size() > _order - 1) {
+    int min_knot = _order;
+    int max_knot = (int)_vertices.size() + 1;
+    
+    for (int i = min_knot; i <= max_knot; i++) {
+      nassertv(i - 1 >= 0 && i < (int)_knots.size());
+      if (_knots[i - 1] < _knots[i]) {
+        // Here's a non-empty segment.
+        _basis.append_segment(_order, i - _order, &_knots[i - _order]);
+      }
+    }
+  }
+
+  _basis_dirty = false;
+}

+ 87 - 0
panda/src/parametrics/nurbsCurveEvaluator.h

@@ -0,0 +1,87 @@
+// Filename: nurbsCurveEvaluator.h
+// Created by:  drose (03Dec02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 NURBSCURVEEVALUATOR_H
+#define NURBSCURVEEVALUATOR_H
+
+#include "pandabase.h"
+#include "nurbsMatrixVector.h"
+#include "nurbsCurveResult.h"
+#include "nurbsVertex.h"
+#include "pointerTo.h"
+#include "vector_float.h"
+#include "pvector.h"
+#include "nodePath.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : NurbsCurveEvaluator
+// Description : This class is an abstraction for evaluating NURBS
+//               curves.  It accepts an array of vertices, each of
+//               which may be in a different coordinate space (as
+//               defined by a NodePath), as well as an optional knot
+//               vector.
+//
+//               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 NurbsCurveEvaluator {
+PUBLISHED:
+  NurbsCurveEvaluator();
+  ~NurbsCurveEvaluator();
+
+  void set_order(int order);
+  int get_order() const;
+
+  void reset(int num_vertices);
+
+  int get_num_vertices() const;
+  void set_vertex(int i, const LVecBase4f &vertex);
+  const LVecBase4f &get_vertex(int i) const;
+
+  void set_vertex_space(int i, const NodePath &space);
+  const NodePath &get_vertex_space(int i) const;
+
+  int get_num_knots() const;
+  void set_knot(int i, float knot);
+  float get_knot(int i) const;
+
+  PT(NurbsCurveResult) evaluate(const NodePath &rel_to = NodePath());
+
+private:
+  void recompute_knots();
+  void recompute_basis();
+
+  int _order;
+
+  typedef pvector<NurbsVertex> Vertices;
+  Vertices _vertices;
+
+  bool _knots_dirty;
+  typedef vector_float Knots;
+  Knots _knots;
+
+  bool _basis_dirty;
+  NurbsMatrixVector _basis;
+};
+
+#endif
+

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

@@ -0,0 +1,39 @@
+// Filename: nurbsCurveResult.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: NurbsCurveResult::get_start_t
+//       Access: Public
+//  Description: Returns the first legal value of t on the curve.
+//               Usually this is 0.0.
+////////////////////////////////////////////////////////////////////
+INLINE float NurbsCurveResult::
+get_start_t() const {
+  return _prod.get_start_t();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsCurveResult::get_end_t
+//       Access: Public
+//  Description: Returns the last legal value of t on the curve.
+////////////////////////////////////////////////////////////////////
+INLINE float NurbsCurveResult::
+get_end_t() const {
+  return _prod.get_end_t();
+}

+ 153 - 0
panda/src/parametrics/nurbsCurveResult.cxx

@@ -0,0 +1,153 @@
+// Filename: nurbsCurveResult.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 "nurbsCurveResult.h"
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsCurveResult::Constructor
+//       Access: Public
+//  Description: The constructor automatically builds up the result as
+//               the product of the indicated set of basis matrices
+//               and the indicated table of control vertex positions.
+////////////////////////////////////////////////////////////////////
+NurbsCurveResult::
+NurbsCurveResult(const NurbsMatrixVector &basis, int order,
+                 const LVecBase4f verts[], int num_vertices) {
+  _last_segment = -1;
+
+  int num_segments = basis.get_num_segments();
+  for (int i = 0; i < num_segments; i++) {
+    int vi = basis.get_vertex_index(i);
+    nassertv(vi >= 0 && vi < num_vertices);
+
+    // Create a matrix from our (up to) four involved vertices.
+    LMatrix4f geom;
+    int ci = 0;
+    while (ci < order) {
+      geom.set_row(ci, verts[vi + ci]);
+      ci++;
+    }
+    while (ci < 4) {
+      geom.set_row(ci, LVecBase4f::zero());
+      ci++;
+    }
+
+    // And compose this matrix with the segment to produce a new
+    // matrix.
+    _prod.compose_segment(basis, i, geom);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsCurveResult::Destructor
+//       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.
+////////////////////////////////////////////////////////////////////
+bool NurbsCurveResult::
+eval_point(float t, LPoint3f &point) {
+  int segment = find_segment(t);
+  if (segment == -1) {
+    return false;
+  }
+
+  t = _prod.scale_t(segment, t);
+  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;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsCurveResult::find_segment
+//       Access: Private
+//  Description: Returns the index of the segment that contains the
+//               indicated value of t, or -1 if no segment contains
+//               this value.
+////////////////////////////////////////////////////////////////////
+int NurbsCurveResult::
+find_segment(float t) {
+  // Trivially check the endpoints of the curve.
+  if (t >= get_end_t()) {
+    return _prod.get_num_segments() - 1;
+  } else if (t <= get_start_t()) {
+    return 0;
+  }
+
+  // Check the last segment we searched for.  Often, two consecutive
+  // requests are for the same segment.
+  if (_last_segment != -1 && (t >= _last_from && t < _last_to)) {
+    return _last_segment;
+  }
+
+  // Look for the segment the hard way.
+  int segment = r_find_segment(t, 0, _prod.get_num_segments() - 1);
+  if (segment != -1) {
+    _last_segment = segment;
+    _last_from = _prod.get_from(segment);
+    _last_to = _prod.get_to(segment);
+  }
+  return segment;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsCurveResult::r_find_segment
+//       Access: Private
+//  Description: Recursively searches for the segment that contains
+//               the indicated value of t by performing a binary
+//               search.  This assumes the segments are stored in
+//               increasing order of t, and they don't overlap.
+////////////////////////////////////////////////////////////////////
+int NurbsCurveResult::
+r_find_segment(float t, int top, int bot) const {
+  if (bot < top) {
+    // Not found.
+    return -1;
+  }
+  int mid = (top + bot) / 2;
+  nassertr(mid >= 0 && mid < _prod.get_num_segments(), -1);
+
+  float from = _prod.get_from(mid);
+  float to = _prod.get_to(mid);
+  if (from > t) {
+    // Too high, try lower.
+    return r_find_segment(t, top, mid - 1);
+
+  } else if (to <= t) {
+    // Too low, try higher.
+    return r_find_segment(t, mid + 1, bot);
+
+  } else {
+    // Here we are!
+    return mid;
+  }
+}

+ 69 - 0
panda/src/parametrics/nurbsCurveResult.h

@@ -0,0 +1,69 @@
+// Filename: nurbsCurveResult.h
+// Created by:  drose (03Dec02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 NURBSCURVERESULT_H
+#define NURBSCURVERESULT_H
+
+#include "pandabase.h"
+#include "referenceCount.h"
+#include "nurbsMatrixVector.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : NurbsCurveResult
+// Description : The result of a NurbsCurveEvaluator.  This object
+//               represents a curve in a particular coordinate space.
+//               It can return the point and/or tangent to the curve
+//               at any point.
+//
+//               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 NurbsCurveResult : public ReferenceCount {
+public:
+  NurbsCurveResult(const NurbsMatrixVector &basis, int order,
+                   const LVecBase4f verts[], int num_vertices);
+
+PUBLISHED:
+  ~NurbsCurveResult();
+
+  INLINE float get_start_t() const;
+  INLINE float get_end_t() const;
+
+  bool eval_point(float t, LPoint3f &point);
+  
+private:
+  int find_segment(float t);
+  int r_find_segment(float t, int top, int bot) const;
+
+  NurbsMatrixVector _prod;
+
+  int _last_segment;
+  float _last_from;
+  float _last_to;
+
+  friend class NurbsCurveEvaluator;
+};
+
+#include "nurbsCurveResult.I"
+
+#endif
+

+ 132 - 0
panda/src/parametrics/nurbsMatrixVector.I

@@ -0,0 +1,132 @@
+// Filename: nurbsMatrixVector.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: NurbsMatrixVector::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE NurbsMatrixVector::
+NurbsMatrixVector() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsMatrixVector::Destructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE NurbsMatrixVector::
+~NurbsMatrixVector() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsMatrixVector::get_num_segments
+//       Access: Public
+//  Description: Returns the number of piecewise continuous segments
+//               in the curve.
+////////////////////////////////////////////////////////////////////
+INLINE int NurbsMatrixVector::
+get_num_segments() const {
+  return _segments.size();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsMatrixVector::get_start_t
+//       Access: Public
+//  Description: Returns the first legal value of t on the curve.
+//               Usually this is 0.0.
+////////////////////////////////////////////////////////////////////
+INLINE float NurbsMatrixVector::
+get_start_t() const {
+  nassertr(!_segments.empty(), 0.0f);
+  return _segments.front()._from;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsMatrixVector::get_end_t
+//       Access: Public
+//  Description: Returns the last legal value of t on the curve.
+////////////////////////////////////////////////////////////////////
+INLINE float NurbsMatrixVector::
+get_end_t() const {
+  nassertr(!_segments.empty(), 0.0f);
+  return _segments.back()._to;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsMatrixVector::get_vertex_index
+//       Access: Public
+//  Description: Returns the vertex index of the nth segment.  This is
+//               the index number of the first associated control
+//               vertex within the source NurbsCurveEvaluator object.
+////////////////////////////////////////////////////////////////////
+INLINE int NurbsMatrixVector::
+get_vertex_index(int segment) const {
+  nassertr(segment >= 0 && segment < (int)_segments.size(), 0);
+  return _segments[segment]._vertex_index;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsMatrixVector::get_from
+//       Access: Public
+//  Description: Returns the t value of the beginning of this segment.
+////////////////////////////////////////////////////////////////////
+INLINE float NurbsMatrixVector::
+get_from(int segment) const {
+  nassertr(segment >= 0 && segment < (int)_segments.size(), 0.0f);
+  return _segments[segment]._from;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsMatrixVector::get_to
+//       Access: Public
+//  Description: Returns the t value of the end of this segment.
+////////////////////////////////////////////////////////////////////
+INLINE float NurbsMatrixVector::
+get_to(int segment) const {
+  nassertr(segment >= 0 && segment < (int)_segments.size(), 0.0f);
+  return _segments[segment]._to;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsMatrixVector::get_matrix
+//       Access: Public
+//  Description: Returns the matrix associated with the nth segment.
+////////////////////////////////////////////////////////////////////
+INLINE const LMatrix4f &NurbsMatrixVector::
+get_matrix(int segment) const {
+  nassertr(segment >= 0 && segment < (int)_segments.size(), LMatrix4f::ident_mat());
+  return _segments[segment]._matrix;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsMatrixVector::scale_t
+//       Access: Public
+//  Description: Scales the value of t into the range [0, 1]
+//               corresponding to [from, to].  Returns the scaled
+//               value.
+////////////////////////////////////////////////////////////////////
+INLINE float NurbsMatrixVector::
+scale_t(int segment, float t) const {
+  nassertr(segment >= 0 && segment < (int)_segments.size(), 0.0f);
+  float from = _segments[segment]._from;
+  float to = _segments[segment]._to;
+  t = (t - from) / (to - from);
+  return min(max(t, 0.0f), 1.0f);
+}

+ 150 - 0
panda/src/parametrics/nurbsMatrixVector.cxx

@@ -0,0 +1,150 @@
+// Filename: nurbsMatrixVector.cxx
+// Created by:  drose (03Dec02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "nurbsMatrixVector.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsMatrixVector::clear
+//       Access: Public
+//  Description: Removes all the segments from the curve.
+////////////////////////////////////////////////////////////////////
+void NurbsMatrixVector::
+clear() {
+  _segments.clear();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsMatrixVector::append_segment
+//       Access: Public
+//  Description: Computes a NURBS basis for one segment of the curve
+//               and appends it to the set of basis matrices.
+////////////////////////////////////////////////////////////////////
+void NurbsMatrixVector::
+append_segment(int order, int vertex_index, const float knots[]) {
+  int i;
+
+  // Scale the supplied knots to the range 0..1.
+  float scaled_knots[8];
+  float min_k = knots[order - 1];
+  float max_k = knots[order];
+
+  nassertv(min_k != max_k);
+  for (i = 0; i < order + order; i++) {
+    scaled_knots[i] = (knots[i] - min_k) / (max_k - min_k);
+  }
+
+  Segment segment;
+  segment._vertex_index = vertex_index;
+  segment._from = min_k;
+  segment._to = max_k;
+
+  for (i = 0; i < order; i++) {
+    LVecBase4f b = nurbs_blending_function(order, i, order, scaled_knots);
+    segment._matrix.set_col(i, b);
+  }
+
+  for (i = order; i < 4; i++) {
+    segment._matrix.set_col(i, LVecBase4f::zero());
+  }
+
+  _segments.push_back(segment);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsMatrixVector::compose_segment
+//       Access: Public
+//  Description: Appends a new segment to the vector by composing the
+//               indicated geometry matrix with the indicated basis
+//               matrix from the given vector.
+////////////////////////////////////////////////////////////////////
+void NurbsMatrixVector::
+compose_segment(const NurbsMatrixVector &basis, int segment, 
+                const LMatrix4f &geom) {
+  nassertv(segment >= 0 && segment < (int)basis._segments.size());
+  const Segment &source = basis._segments[segment];
+
+  Segment dest;
+  dest._vertex_index = source._vertex_index;
+  dest._from = source._from;
+  dest._to = source._to;
+  dest._matrix = source._matrix * geom;
+
+  _segments.push_back(dest);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsMatrixVector::nurbs_blending_function
+//       Access: Private, Static
+//  Description: Recursively computes the appropriate blending
+//               function for the indicated knot vector.
+////////////////////////////////////////////////////////////////////
+LVecBase4f NurbsMatrixVector::
+nurbs_blending_function(int order, int i, int j, const float knots[]) {
+  // This is doubly recursive.  Ick.
+  LVecBase4f r;
+
+  if (j == 1) {
+    if (i == order-1 && knots[i] < knots[i+1]) {
+      r.set(0.0f, 0.0f, 0.0f, 1.0f);
+    } else {
+      r.set(0.0f, 0.0f, 0.0f, 0.0f);
+    }
+
+  } else {
+    LVecBase4f bi0 = nurbs_blending_function(order, i, j - 1, knots);
+    LVecBase4f bi1 = nurbs_blending_function(order, i + 1, j - 1, knots);
+
+    float d0 = knots[i + j - 1] - knots[i];
+    float d1 = knots[i + j] - knots[i + 1];
+
+    // First term.  Division by zero is defined to equal zero.
+    if (d0 != 0.0f) {
+      if (d1 != 0.0f) {
+        r = bi0 / d0 - bi1 / d1;
+      } else {
+        r = bi0 / d0;
+      }
+
+    } else if (d1 != 0.0f) {
+      r = - bi1 / d1;
+
+    } else {
+      r.set(0.0f, 0.0f, 0.0f, 0.0f);
+    }
+
+    // scale by t.
+    r[0] = r[1];
+    r[1] = r[2];
+    r[2] = r[3];
+    r[3] = 0.0f;
+
+    // Second term.
+    if (d0 != 0.0f) {
+      if (d1 != 0.0f) {
+        r += bi0 * (- knots[i] / d0) + bi1 * (knots[i + j] / d1);
+      } else {
+        r += bi0 * (- knots[i] / d0);
+      }
+
+    } else if (d1 != 0.0f) {
+      r += bi1 * (knots[i + j] / d1);
+    }
+  }
+
+  return r;
+}

+ 80 - 0
panda/src/parametrics/nurbsMatrixVector.h

@@ -0,0 +1,80 @@
+// Filename: nurbsMatrixVector.h
+// Created by:  drose (03Dec02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 NURBSMATRIXVECTOR_H
+#define NURBSMATRIXVECTOR_H
+
+#include "pandabase.h"
+#include "luse.h"
+#include "pvector.h"
+#include "pmap.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : NurbsMatrixVector
+// Description : This encapsulates a series of matrices that are used
+//               to represent the sequential segments of a
+//               NurbsCurveEvaluator.
+//
+//               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 NurbsMatrixVector {
+public:
+  INLINE NurbsMatrixVector();
+  INLINE ~NurbsMatrixVector();
+
+  INLINE int get_num_segments() const;
+  INLINE float get_start_t() const;
+  INLINE float get_end_t() const;
+
+  INLINE int get_vertex_index(int segment) const;
+  INLINE float get_from(int segment) const;
+  INLINE float get_to(int segment) const;
+  INLINE const LMatrix4f &get_matrix(int segment) const;
+  INLINE float scale_t(int segment, float t) const;
+
+  void clear();
+  void append_segment(int order, int vertex_index, const float knots[]);
+  void compose_segment(const NurbsMatrixVector &basis, int segment, 
+                       const LMatrix4f &geom);
+
+private:
+  static LVecBase4f nurbs_blending_function(int order, int i, int j, 
+                                            const float knots[]);
+
+private:
+  class Segment {
+  public:
+    int _vertex_index;
+    float _from;
+    float _to;
+    LMatrix4f _matrix;
+  };
+
+  typedef pvector<Segment> Segments;
+  Segments _segments;
+};
+
+#include "nurbsMatrixVector.I"
+
+#endif
+

+ 99 - 0
panda/src/parametrics/nurbsVertex.I

@@ -0,0 +1,99 @@
+// Filename: nurbsVertex.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: NurbsVertex::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE NurbsVertex::
+NurbsVertex() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsVertex::Copy Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE NurbsVertex::
+NurbsVertex(const NurbsVertex &copy) :
+  _vertex(copy._vertex),
+  _space(copy._space)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsVertex::Copy Assignment Operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void NurbsVertex::
+operator = (const NurbsVertex &copy) {
+  _vertex = copy._vertex;
+  _space = copy._space;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsVertex::Destructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE NurbsVertex::
+~NurbsVertex() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsVertex::set_vertex
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void NurbsVertex::
+set_vertex(const LVecBase4f &vertex) {
+  _vertex = vertex;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsVertex::get_vertex
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE const LVecBase4f &NurbsVertex::
+get_vertex() const {
+  return _vertex;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsVertex::set_space
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void NurbsVertex::
+set_space(const NodePath &space) {
+  _space = space;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NurbsVertex::get_space
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE const NodePath &NurbsVertex::
+get_space() const {
+  return _space;
+}

+ 20 - 0
panda/src/parametrics/nurbsVertex.cxx

@@ -0,0 +1,20 @@
+// Filename: nurbsVertex.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 "nurbsVertex.h"
+

+ 61 - 0
panda/src/parametrics/nurbsVertex.h

@@ -0,0 +1,61 @@
+// Filename: nurbsVertex.h
+// Created by:  drose (03Dec02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 NURBSVERTEX_H
+#define NURBSVERTEX_H
+
+#include "pandabase.h"
+#include "luse.h"
+#include "nodePath.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : NurbsVertex
+// Description : This represents a single control vertex in a
+//               NurbsEvaluator.  It may be relative to a particular
+//               coordinate space; or its coordinate space may be
+//               unspecified.
+//
+//               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 NurbsVertex {
+public:
+  INLINE NurbsVertex();
+  INLINE NurbsVertex(const NurbsVertex &copy);
+  INLINE void operator = (const NurbsVertex &copy);
+  INLINE ~NurbsVertex();
+
+  INLINE void set_vertex(const LVecBase4f &vertex);
+  INLINE const LVecBase4f &get_vertex() const;
+
+  INLINE void set_space(const NodePath &space);
+  INLINE const NodePath &get_space() const;
+
+private:
+  LVecBase4f _vertex;
+  NodePath _space;
+};
+
+#include "nurbsVertex.I"
+
+#endif
+

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

@@ -1,9 +1,6 @@
-
 #include "classicNurbsCurve.cxx"
 #include "cubicCurveseg.cxx"
 #include "curveFitter.cxx"
 #include "hermiteCurve.cxx"
 #include "nurbsCurveDrawer.cxx"
 #include "nurbsCurveInterface.cxx"
-
-

+ 4 - 3
panda/src/parametrics/parametrics_composite2.cxx

@@ -1,8 +1,9 @@
-
 #include "config_parametrics.cxx"
 #include "piecewiseCurve.cxx"
 #include "parametricCurve.cxx"
 #include "parametricCurveCollection.cxx"
 #include "parametricCurveDrawer.cxx"
-
-
+#include "nurbsCurveEvaluator.cxx"
+#include "nurbsCurveResult.cxx"
+#include "nurbsMatrixVector.cxx"
+#include "nurbsVertex.cxx"