first pass at NurbsCurveEvaluator

This commit is contained in:
David Rose 2002-12-04 23:29:03 +00:00
parent 23d9bf4583
commit 340d20717e
14 changed files with 1213 additions and 20 deletions

View File

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

View File

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

View File

@ -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<NurbsVertex> Vertices;
Vertices _vertices;
bool _knots_dirty;
typedef vector_float Knots;
Knots _knots;
bool _basis_dirty;
NurbsMatrixVector _basis;
};
#endif

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<Segment> Segments;
Segments _segments;
};
#include "nurbsMatrixVector.I"
#endif

View File

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

View File

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

View File

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

View File

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

View File

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