diff --git a/panda/src/parametrics/Sources.pp b/panda/src/parametrics/Sources.pp index 4ac7725ea2..cc4c98c480 100644 --- a/panda/src/parametrics/Sources.pp +++ b/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 \ diff --git a/panda/src/parametrics/nurbsCurveEvaluator.cxx b/panda/src/parametrics/nurbsCurveEvaluator.cxx new file mode 100644 index 0000000000..b91a8ec9ea --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#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 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; +} diff --git a/panda/src/parametrics/nurbsCurveEvaluator.h b/panda/src/parametrics/nurbsCurveEvaluator.h new file mode 100644 index 0000000000..20425247de --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#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 Vertices; + Vertices _vertices; + + bool _knots_dirty; + typedef vector_float Knots; + Knots _knots; + + bool _basis_dirty; + NurbsMatrixVector _basis; +}; + +#endif + diff --git a/panda/src/parametrics/nurbsCurveResult.I b/panda/src/parametrics/nurbsCurveResult.I new file mode 100644 index 0000000000..fa051d040f --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// 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(); +} diff --git a/panda/src/parametrics/nurbsCurveResult.cxx b/panda/src/parametrics/nurbsCurveResult.cxx new file mode 100644 index 0000000000..0e80702062 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#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; + } +} diff --git a/panda/src/parametrics/nurbsCurveResult.h b/panda/src/parametrics/nurbsCurveResult.h new file mode 100644 index 0000000000..73f9e48595 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#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 + diff --git a/panda/src/parametrics/nurbsMatrixVector.I b/panda/src/parametrics/nurbsMatrixVector.I new file mode 100644 index 0000000000..70a5e47ff6 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// 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); +} diff --git a/panda/src/parametrics/nurbsMatrixVector.cxx b/panda/src/parametrics/nurbsMatrixVector.cxx new file mode 100644 index 0000000000..4521a76c7f --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#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; +} diff --git a/panda/src/parametrics/nurbsMatrixVector.h b/panda/src/parametrics/nurbsMatrixVector.h new file mode 100644 index 0000000000..492845c2b1 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#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 Segments; + Segments _segments; +}; + +#include "nurbsMatrixVector.I" + +#endif + diff --git a/panda/src/parametrics/nurbsVertex.I b/panda/src/parametrics/nurbsVertex.I new file mode 100644 index 0000000000..53e876092c --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: NurbsVertex::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE NurbsVertex:: +NurbsVertex() { +} + +//////////////////////////////////////////////////////////////////// +// Function: NurbsVertex::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE NurbsVertex:: +NurbsVertex(const NurbsVertex ©) : + _vertex(copy._vertex), + _space(copy._space) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: NurbsVertex::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void NurbsVertex:: +operator = (const NurbsVertex ©) { + _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; +} diff --git a/panda/src/parametrics/nurbsVertex.cxx b/panda/src/parametrics/nurbsVertex.cxx new file mode 100644 index 0000000000..1cd9c35e08 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "nurbsVertex.h" + diff --git a/panda/src/parametrics/nurbsVertex.h b/panda/src/parametrics/nurbsVertex.h new file mode 100644 index 0000000000..ad5d672186 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#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 ©); + INLINE void operator = (const NurbsVertex ©); + 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 + diff --git a/panda/src/parametrics/parametrics_composite1.cxx b/panda/src/parametrics/parametrics_composite1.cxx index e9bd4cdbba..a16667f780 100644 --- a/panda/src/parametrics/parametrics_composite1.cxx +++ b/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" - - diff --git a/panda/src/parametrics/parametrics_composite2.cxx b/panda/src/parametrics/parametrics_composite2.cxx index 6bac1f5c72..194fa3028f 100644 --- a/panda/src/parametrics/parametrics_composite2.cxx +++ b/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"