mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
add NurbsSurfaceEvaluator
This commit is contained in:
parent
41232c24d9
commit
a356726b35
@ -20,6 +20,8 @@
|
||||
nurbsCurveInterface.I nurbsCurveInterface.h \
|
||||
nurbsCurveResult.I nurbsCurveResult.h \
|
||||
nurbsBasisVector.I nurbsBasisVector.h \
|
||||
nurbsSurfaceEvaluator.I nurbsSurfaceEvaluator.h \
|
||||
nurbsSurfaceResult.I nurbsSurfaceResult.h \
|
||||
nurbsVertex.h nurbsVertex.I \
|
||||
parametricCurve.h \
|
||||
parametricCurveCollection.I parametricCurveCollection.h \
|
||||
@ -33,9 +35,11 @@
|
||||
parametricCurveDrawer.cxx curveFitter.cxx hermiteCurve.cxx \
|
||||
nurbsCurveDrawer.cxx \
|
||||
nurbsCurveEvaluator.cxx \
|
||||
nurbsCurveResult.cxx \
|
||||
nurbsCurveInterface.cxx \
|
||||
nurbsCurveResult.cxx \
|
||||
nurbsBasisVector.cxx \
|
||||
nurbsSurfaceEvaluator.cxx \
|
||||
nurbsSurfaceResult.cxx \
|
||||
nurbsVertex.cxx \
|
||||
parametricCurve.cxx parametricCurveCollection.cxx \
|
||||
piecewiseCurve.cxx \
|
||||
@ -54,6 +58,8 @@
|
||||
nurbsCurveInterface.I nurbsCurveInterface.h \
|
||||
nurbsCurveResult.I nurbsCurveResult.h \
|
||||
nurbsBasisVector.I nurbsBasisVector.h \
|
||||
nurbsSurfaceEvaluator.I nurbsSurfaceEvaluator.h \
|
||||
nurbsSurfaceResult.I nurbsSurfaceResult.h \
|
||||
nurbsVertex.h nurbsVertex.I \
|
||||
nurbsPPCurve.h \
|
||||
parametricCurve.h \
|
||||
|
@ -40,7 +40,7 @@ NurbsCurveResult(const NurbsBasisVector &basis,
|
||||
_composed.reserve(num_segments);
|
||||
for (int i = 0; i < num_segments; i++) {
|
||||
int vi = _basis.get_vertex_index(i);
|
||||
nassertv(vi >= 0 && vi < num_vertices);
|
||||
nassertv(vi >= 0 && vi + order - 1 < num_vertices);
|
||||
|
||||
// Create a geometry matrix from our (up to) four involved vertices.
|
||||
LMatrix4f geom;
|
||||
@ -86,6 +86,7 @@ eval_segment_point(int segment, float t, LVecBase3f &point) const {
|
||||
LVecBase4f tvec(t*t2, t2, t, 1.0f);
|
||||
|
||||
float weight = tvec.dot(_composed[segment].get_col(3));
|
||||
|
||||
point.set(tvec.dot(_composed[segment].get_col(0)) / weight,
|
||||
tvec.dot(_composed[segment].get_col(1)) / weight,
|
||||
tvec.dot(_composed[segment].get_col(2)) / weight);
|
||||
|
@ -70,7 +70,7 @@ private:
|
||||
|
||||
// We pre-compose the basis matrix and the geometry vectors, so we
|
||||
// have these handy for evaluation. There is one entry in the
|
||||
// _composed_vector for each entry in basis._segments.
|
||||
// _composed for each entry in basis._segments.
|
||||
typedef pvector<LMatrix4f> ComposedGeom;
|
||||
ComposedGeom _composed;
|
||||
|
||||
|
271
panda/src/parametrics/nurbsSurfaceEvaluator.I
Normal file
271
panda/src/parametrics/nurbsSurfaceEvaluator.I
Normal file
@ -0,0 +1,271 @@
|
||||
// Filename: nurbsSurfaceEvaluator.I
|
||||
// Created by: drose (10Oct03)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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: NurbsSurfaceEvaluator::set_u_order
|
||||
// Access: Published
|
||||
// Description: Sets the order of the surface in the U direction.
|
||||
// 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 surface.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void NurbsSurfaceEvaluator::
|
||||
set_u_order(int u_order) {
|
||||
_u_order = u_order;
|
||||
_u_knots_dirty = true;
|
||||
_u_basis_dirty = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::get_u_order
|
||||
// Access: Published
|
||||
// Description: Returns the order of the surface in the U direction
|
||||
// as set by a previous call to set_u_order().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int NurbsSurfaceEvaluator::
|
||||
get_u_order() const {
|
||||
return _u_order;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::set_v_order
|
||||
// Access: Published
|
||||
// Description: Sets the order of the surface in the V direction.
|
||||
// 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 surface.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void NurbsSurfaceEvaluator::
|
||||
set_v_order(int v_order) {
|
||||
_v_order = v_order;
|
||||
_v_knots_dirty = true;
|
||||
_v_basis_dirty = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::get_v_order
|
||||
// Access: Published
|
||||
// Description: Returns the order of the surface in the V direction
|
||||
// as set by a previous call to set_v_order().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int NurbsSurfaceEvaluator::
|
||||
get_v_order() const {
|
||||
return _v_order;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::get_num_u_vertices
|
||||
// Access: Published
|
||||
// Description: Returns the number of control vertices in the U
|
||||
// direction on the surface. This is the number passed
|
||||
// to the last call to reset().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int NurbsSurfaceEvaluator::
|
||||
get_num_u_vertices() const {
|
||||
return _num_u_vertices;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::get_num_v_vertices
|
||||
// Access: Published
|
||||
// Description: Returns the number of control vertices in the V
|
||||
// direction on the surface. This is the number passed
|
||||
// to the last call to reset().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int NurbsSurfaceEvaluator::
|
||||
get_num_v_vertices() const {
|
||||
return _num_v_vertices;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::set_vertex
|
||||
// Access: Published
|
||||
// Description: Sets the nth control vertex of the surface, as a vertex
|
||||
// in 4-d homogeneous space. In this form, the first
|
||||
// three components of the vertex should already have
|
||||
// been scaled by the fourth component, which is the
|
||||
// homogeneous weight.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void NurbsSurfaceEvaluator::
|
||||
set_vertex(int ui, int vi, const LVecBase4f &vertex) {
|
||||
nassertv(ui >= 0 && ui < _num_u_vertices &&
|
||||
vi >= 0 && vi < _num_v_vertices);
|
||||
vert(ui, vi).set_vertex(vertex);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::set_vertex
|
||||
// Access: Published
|
||||
// Description: Sets the nth control vertex of the surface. This
|
||||
// flavor sets the vertex as a 3-d coordinate and a
|
||||
// weight; the 3-d coordinate values are implicitly
|
||||
// scaled up by the weight factor.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void NurbsSurfaceEvaluator::
|
||||
set_vertex(int ui, int vi, const LVecBase3f &vertex, float weight) {
|
||||
nassertv(ui >= 0 && ui < _num_u_vertices &&
|
||||
vi >= 0 && vi < _num_v_vertices);
|
||||
vert(ui, vi).set_vertex(LVecBase4f(vertex[0] * weight, vertex[1] * weight, vertex[2] * weight, weight));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::get_vertex
|
||||
// Access: Published
|
||||
// Description: Returns the nth control vertex of the surface, relative
|
||||
// to its indicated coordinate space.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const LVecBase4f &NurbsSurfaceEvaluator::
|
||||
get_vertex(int ui, int vi) const {
|
||||
nassertr(ui >= 0 && ui < _num_u_vertices &&
|
||||
vi >= 0 && vi < _num_v_vertices, LVecBase4f::zero());
|
||||
return vert(ui, vi).get_vertex();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::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().
|
||||
//
|
||||
// This specifies the space as a fixed NodePath, which
|
||||
// is always the same NodePath. Also see setting the
|
||||
// space as a path string, which can specify a different
|
||||
// NodePath for different instances of the surface.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void NurbsSurfaceEvaluator::
|
||||
set_vertex_space(int ui, int vi, const NodePath &space) {
|
||||
nassertv(ui >= 0 && ui < _num_u_vertices &&
|
||||
vi >= 0 && vi < _num_v_vertices);
|
||||
vert(ui, vi).set_space(space);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::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
|
||||
// string, the nth control vertex is deemed to be in
|
||||
// the coordinate space passed to evaluate().
|
||||
//
|
||||
// This specifies the space as a string, which describes
|
||||
// the path to find the node relative to the rel_to
|
||||
// NodePath when the surface is evaluated.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void NurbsSurfaceEvaluator::
|
||||
set_vertex_space(int ui, int vi, const string &space) {
|
||||
nassertv(ui >= 0 && ui < _num_u_vertices &&
|
||||
vi >= 0 && vi < _num_v_vertices);
|
||||
vert(ui, vi).set_space(space);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::set_extended_vertex
|
||||
// Access: Public
|
||||
// Description: Sets an n-dimensional vertex value. This allows
|
||||
// definition of a NURBS surface or surface in a sparse
|
||||
// n-dimensional space, typically used for associating
|
||||
// additional properties (like color or joint
|
||||
// membership) with each vertex of a surface.
|
||||
//
|
||||
// The value d is an arbitrary integer value and
|
||||
// specifies the dimension of question for this
|
||||
// particular vertex. Any number of dimensions may be
|
||||
// specified, and they need not be consecutive. If a
|
||||
// value for a given dimension is not specified, is it
|
||||
// implicitly 0.0.
|
||||
//
|
||||
// The value is implicitly scaled by the homogenous
|
||||
// weight value--that is, the fourth component of the
|
||||
// value passed to set_vertex(). This means the
|
||||
// ordinary vertex must be set first, before the
|
||||
// extended vertices can be set.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NurbsSurfaceEvaluator::
|
||||
set_extended_vertex(int ui, int vi, int d, float value) {
|
||||
nassertv(ui >= 0 && ui < _num_u_vertices &&
|
||||
vi >= 0 && vi < _num_v_vertices);
|
||||
vert(ui, vi).set_extended_vertex(d, value);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::float_extended_vertex
|
||||
// Access: Public
|
||||
// Description: Returns an n-dimensional vertex value. See
|
||||
// set_extended_vertex(). This returns the value set
|
||||
// for the indicated dimension, or 0.0 if nothing has
|
||||
// been set.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float NurbsSurfaceEvaluator::
|
||||
get_extended_vertex(int ui, int vi, int d) const {
|
||||
nassertr(ui >= 0 && ui < _num_u_vertices &&
|
||||
vi >= 0 && vi < _num_v_vertices, 0.0f);
|
||||
return vert(ui, vi).get_extended_vertex(d);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::get_num_u_knots
|
||||
// Access: Published
|
||||
// Description: Returns the number of knot values in the surface in
|
||||
// the U direction. This is based on the number of
|
||||
// vertices and the order.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int NurbsSurfaceEvaluator::
|
||||
get_num_u_knots() const {
|
||||
return _num_u_vertices + _u_order;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::get_num_v_knots
|
||||
// Access: Published
|
||||
// Description: Returns the number of knot values in the surface in
|
||||
// the V direction. This is based on the number of
|
||||
// vertices and the order.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int NurbsSurfaceEvaluator::
|
||||
get_num_v_knots() const {
|
||||
return _num_v_vertices + _v_order;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::vert
|
||||
// Access: Private
|
||||
// Description: Internal accessor to dereference the 2-d vertex
|
||||
// coordinate pair into a linear list of vertices.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE NurbsVertex &NurbsSurfaceEvaluator::
|
||||
vert(int ui, int vi) {
|
||||
return _vertices[ui * _num_v_vertices + vi];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::vert
|
||||
// Access: Private
|
||||
// Description: Internal accessor to dereference the 2-d vertex
|
||||
// coordinate pair into a linear list of vertices.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const NurbsVertex &NurbsSurfaceEvaluator::
|
||||
vert(int ui, int vi) const {
|
||||
return _vertices[ui * _num_v_vertices + vi];
|
||||
}
|
353
panda/src/parametrics/nurbsSurfaceEvaluator.cxx
Normal file
353
panda/src/parametrics/nurbsSurfaceEvaluator.cxx
Normal file
@ -0,0 +1,353 @@
|
||||
// Filename: nurbsSurfaceEvaluator.cxx
|
||||
// Created by: drose (10Oct03)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "nurbsSurfaceEvaluator.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
NurbsSurfaceEvaluator::
|
||||
NurbsSurfaceEvaluator() {
|
||||
_u_order = 4;
|
||||
_v_order = 4;
|
||||
_u_knots_dirty = true;
|
||||
_v_knots_dirty = true;
|
||||
_u_basis_dirty = true;
|
||||
_v_basis_dirty = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::Destructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
NurbsSurfaceEvaluator::
|
||||
~NurbsSurfaceEvaluator() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::reset
|
||||
// Access: Published
|
||||
// Description: Resets all the vertices and knots to their default
|
||||
// values, and sets the surface up with the indicated
|
||||
// number of vertices. You must then call set_vertex()
|
||||
// repeatedly to fill in all of the vertex values
|
||||
// appropriately.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NurbsSurfaceEvaluator::
|
||||
reset(int num_u_vertices, int num_v_vertices) {
|
||||
int num_vertices = num_u_vertices * num_v_vertices;
|
||||
_vertices.clear();
|
||||
_vertices.reserve(num_vertices);
|
||||
_num_u_vertices = num_u_vertices;
|
||||
_num_v_vertices = num_v_vertices;
|
||||
|
||||
for (int i = 0; i < num_vertices; i++) {
|
||||
_vertices.push_back(NurbsVertex());
|
||||
}
|
||||
_u_knots_dirty = true;
|
||||
_v_knots_dirty = true;
|
||||
_u_basis_dirty = true;
|
||||
_v_basis_dirty = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::get_vertex_space
|
||||
// Access: Published
|
||||
// Description: Returns the coordinate space of the nth control
|
||||
// vertex of the surface, expressed as a NodePath.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
NodePath NurbsSurfaceEvaluator::
|
||||
get_vertex_space(int ui, int vi, const NodePath &rel_to) const {
|
||||
#ifndef NDEBUG
|
||||
static NodePath empty_node_path;
|
||||
nassertr(ui >= 0 && ui < _num_u_vertices &&
|
||||
vi >= 0 && vi < _num_v_vertices, empty_node_path);
|
||||
#endif
|
||||
return vert(ui, vi).get_space(rel_to);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::set_u_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 NurbsSurfaceEvaluator::
|
||||
set_u_knot(int i, float knot) {
|
||||
if (_u_knots_dirty) {
|
||||
recompute_u_knots();
|
||||
}
|
||||
nassertv(i >= 0 && i < (int)_u_knots.size());
|
||||
_u_knots[i] = knot;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::get_u_knot
|
||||
// Access: Published
|
||||
// Description: Returns the value of the nth knot.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float NurbsSurfaceEvaluator::
|
||||
get_u_knot(int i) const {
|
||||
if (_u_knots_dirty) {
|
||||
((NurbsSurfaceEvaluator *)this)->recompute_u_knots();
|
||||
}
|
||||
nassertr(i >= 0 && i < (int)_u_knots.size(), 0.0f);
|
||||
return _u_knots[i];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::set_v_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 NurbsSurfaceEvaluator::
|
||||
set_v_knot(int i, float knot) {
|
||||
if (_v_knots_dirty) {
|
||||
recompute_v_knots();
|
||||
}
|
||||
nassertv(i >= 0 && i < (int)_v_knots.size());
|
||||
_v_knots[i] = knot;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::get_v_knot
|
||||
// Access: Published
|
||||
// Description: Returns the value of the nth knot.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float NurbsSurfaceEvaluator::
|
||||
get_v_knot(int i) const {
|
||||
if (_v_knots_dirty) {
|
||||
((NurbsSurfaceEvaluator *)this)->recompute_v_knots();
|
||||
}
|
||||
nassertr(i >= 0 && i < (int)_v_knots.size(), 0.0f);
|
||||
return _v_knots[i];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::evaluate
|
||||
// Access: Published
|
||||
// Description: Returns a NurbsSurfaceResult 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(NurbsSurfaceResult) NurbsSurfaceEvaluator::
|
||||
evaluate(const NodePath &rel_to) const {
|
||||
if (_u_basis_dirty) {
|
||||
((NurbsSurfaceEvaluator *)this)->recompute_u_basis();
|
||||
}
|
||||
if (_v_basis_dirty) {
|
||||
((NurbsSurfaceEvaluator *)this)->recompute_v_basis();
|
||||
}
|
||||
|
||||
// First, transform the vertices as appropriate.
|
||||
pvector<LVecBase4f> vecs;
|
||||
get_vertices(vecs, rel_to);
|
||||
|
||||
// And apply those transformed vertices to the basis matrices to
|
||||
// derive the result.
|
||||
return new NurbsSurfaceResult(_u_basis, _v_basis,
|
||||
&vecs[0], &_vertices[0],
|
||||
_num_u_vertices, _num_v_vertices);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::get_vertices
|
||||
// Access: Public
|
||||
// Description: Fills the indicated vector with the set of vertices
|
||||
// in the surface, transformed to the given space. This
|
||||
// flavor returns the vertices in 4-dimensional
|
||||
// homogenous space.
|
||||
//
|
||||
// Vertices are arranged in linear sequence, with the v
|
||||
// coordinate changing more rapidly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NurbsSurfaceEvaluator::
|
||||
get_vertices(pvector<LVecBase4f> &verts, const NodePath &rel_to) const {
|
||||
int num_vertices = (int)_vertices.size();
|
||||
verts.reserve(verts.size() + num_vertices);
|
||||
int vi;
|
||||
for (vi = 0; vi < num_vertices; vi++) {
|
||||
NodePath space = _vertices[vi].get_space(rel_to);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::get_vertices
|
||||
// Access: Public
|
||||
// Description: Fills the indicated vector with the set of vertices
|
||||
// in the surface, transformed to the given space. This
|
||||
// flavor returns the vertices in 4-dimensional
|
||||
// homogenous space.
|
||||
//
|
||||
// Vertices are arranged in linear sequence, with the v
|
||||
// coordinate changing more rapidly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NurbsSurfaceEvaluator::
|
||||
get_vertices(pvector<LPoint3f> &verts, const NodePath &rel_to) const {
|
||||
int num_vertices = (int)_vertices.size();
|
||||
verts.reserve(verts.size() + num_vertices);
|
||||
int vi;
|
||||
for (vi = 0; vi < num_vertices; vi++) {
|
||||
const NodePath &space = _vertices[vi].get_space(rel_to);
|
||||
LVecBase4f vertex = _vertices[vi].get_vertex();
|
||||
if (!space.is_empty()) {
|
||||
const LMatrix4f &mat = space.get_mat(rel_to);
|
||||
vertex = vertex * mat;
|
||||
}
|
||||
LPoint3f v3(vertex[0] / vertex[3], vertex[1] / vertex[3], vertex[2] / vertex[3]);
|
||||
verts.push_back(v3);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::recompute_u_knots
|
||||
// Access: Private
|
||||
// Description: Creates a default knot vector.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NurbsSurfaceEvaluator::
|
||||
recompute_u_knots() {
|
||||
_u_knots.clear();
|
||||
int num_knots = get_num_u_knots();
|
||||
_u_knots.reserve(num_knots);
|
||||
|
||||
float value = 0.0f;
|
||||
|
||||
int i = 0;
|
||||
while (i < _u_order) {
|
||||
_u_knots.push_back(value);
|
||||
i++;
|
||||
}
|
||||
while (i < num_knots - _u_order) {
|
||||
value += 1.0f;
|
||||
_u_knots.push_back(value);
|
||||
i++;
|
||||
}
|
||||
value += 1.0f;
|
||||
while (i < num_knots) {
|
||||
_u_knots.push_back(value);
|
||||
i++;
|
||||
}
|
||||
|
||||
_u_knots_dirty = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::recompute_v_knots
|
||||
// Access: Private
|
||||
// Description: Creates a default knot vector.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NurbsSurfaceEvaluator::
|
||||
recompute_v_knots() {
|
||||
_v_knots.clear();
|
||||
int num_knots = get_num_v_knots();
|
||||
_v_knots.reserve(num_knots);
|
||||
|
||||
float value = 0.0f;
|
||||
|
||||
int i = 0;
|
||||
while (i < _v_order) {
|
||||
_v_knots.push_back(value);
|
||||
i++;
|
||||
}
|
||||
while (i < num_knots - _v_order) {
|
||||
value += 1.0f;
|
||||
_v_knots.push_back(value);
|
||||
i++;
|
||||
}
|
||||
value += 1.0f;
|
||||
while (i < num_knots) {
|
||||
_v_knots.push_back(value);
|
||||
i++;
|
||||
}
|
||||
|
||||
_v_knots_dirty = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::recompute_u_basis
|
||||
// Access: Private
|
||||
// Description: Recomputes the basis matrices according to the knot
|
||||
// vector.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NurbsSurfaceEvaluator::
|
||||
recompute_u_basis() {
|
||||
if (_u_knots_dirty) {
|
||||
((NurbsSurfaceEvaluator *)this)->recompute_u_knots();
|
||||
}
|
||||
|
||||
_u_basis.clear(_u_order);
|
||||
if (_num_u_vertices > _u_order - 1) {
|
||||
int min_knot = _u_order;
|
||||
int max_knot = _num_u_vertices + 1;
|
||||
|
||||
for (int i = min_knot; i <= max_knot; i++) {
|
||||
nassertv(i - 1 >= 0 && i < (int)_u_knots.size());
|
||||
if (_u_knots[i - 1] < _u_knots[i]) {
|
||||
// Here's a non-empty segment.
|
||||
_u_basis.append_segment(i - _u_order, &_u_knots[i - _u_order]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_u_basis_dirty = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceEvaluator::recompute_v_basis
|
||||
// Access: Private
|
||||
// Description: Recomputes the basis matrices according to the knot
|
||||
// vector.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NurbsSurfaceEvaluator::
|
||||
recompute_v_basis() {
|
||||
if (_v_knots_dirty) {
|
||||
((NurbsSurfaceEvaluator *)this)->recompute_v_knots();
|
||||
}
|
||||
|
||||
_v_basis.clear(_v_order);
|
||||
if (_num_v_vertices > _v_order - 1) {
|
||||
int min_knot = _v_order;
|
||||
int max_knot = _num_v_vertices + 1;
|
||||
|
||||
for (int i = min_knot; i <= max_knot; i++) {
|
||||
nassertv(i - 1 >= 0 && i < (int)_v_knots.size());
|
||||
if (_v_knots[i - 1] < _v_knots[i]) {
|
||||
// Here's a non-empty segment.
|
||||
_v_basis.append_segment(i - _v_order, &_v_knots[i - _v_order]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_v_basis_dirty = false;
|
||||
}
|
113
panda/src/parametrics/nurbsSurfaceEvaluator.h
Normal file
113
panda/src/parametrics/nurbsSurfaceEvaluator.h
Normal file
@ -0,0 +1,113 @@
|
||||
// Filename: nurbsSurfaceEvaluator.h
|
||||
// Created by: drose (10Oct03)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 NURBSSURFACEEVALUATOR_H
|
||||
#define NURBSSURFACEEVALUATOR_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "nurbsBasisVector.h"
|
||||
#include "nurbsSurfaceResult.h"
|
||||
#include "nurbsVertex.h"
|
||||
#include "pointerTo.h"
|
||||
#include "vector_float.h"
|
||||
#include "pvector.h"
|
||||
#include "nodePath.h"
|
||||
#include "referenceCount.h"
|
||||
#include "luse.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : NurbsSurfaceEvaluator
|
||||
// Description : This class is an abstraction for evaluating NURBS
|
||||
// surfaces. 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.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA NurbsSurfaceEvaluator : public ReferenceCount {
|
||||
PUBLISHED:
|
||||
NurbsSurfaceEvaluator();
|
||||
~NurbsSurfaceEvaluator();
|
||||
|
||||
INLINE void set_u_order(int u_order);
|
||||
INLINE int get_u_order() const;
|
||||
|
||||
INLINE void set_v_order(int v_order);
|
||||
INLINE int get_v_order() const;
|
||||
|
||||
void reset(int num_u_vertices, int num_v_vertices);
|
||||
|
||||
INLINE int get_num_u_vertices() const;
|
||||
INLINE int get_num_v_vertices() const;
|
||||
INLINE void set_vertex(int ui, int vi, const LVecBase4f &vertex);
|
||||
INLINE void set_vertex(int ui, int vi, const LVecBase3f &vertex, float weight = 1.0);
|
||||
INLINE const LVecBase4f &get_vertex(int ui, int vi) const;
|
||||
|
||||
INLINE void set_vertex_space(int ui, int vi, const NodePath &space);
|
||||
INLINE void set_vertex_space(int ui, int vi, const string &space);
|
||||
NodePath get_vertex_space(int ui, int vi, const NodePath &rel_to) const;
|
||||
|
||||
INLINE void set_extended_vertex(int ui, int vi, int d, float value);
|
||||
INLINE float get_extended_vertex(int ui, int vi, int d) const;
|
||||
|
||||
INLINE int get_num_u_knots() const;
|
||||
void set_u_knot(int i, float knot);
|
||||
float get_u_knot(int i) const;
|
||||
|
||||
INLINE int get_num_v_knots() const;
|
||||
void set_v_knot(int i, float knot);
|
||||
float get_v_knot(int i) const;
|
||||
|
||||
PT(NurbsSurfaceResult) evaluate(const NodePath &rel_to = NodePath()) const;
|
||||
|
||||
public:
|
||||
void get_vertices(pvector<LVecBase4f> &verts, const NodePath &rel_to) const;
|
||||
void get_vertices(pvector<LPoint3f> &verts, const NodePath &rel_to) const;
|
||||
|
||||
private:
|
||||
INLINE NurbsVertex &vert(int ui, int vi);
|
||||
INLINE const NurbsVertex &vert(int ui, int vi) const;
|
||||
|
||||
void recompute_u_knots();
|
||||
void recompute_v_knots();
|
||||
void recompute_u_basis();
|
||||
void recompute_v_basis();
|
||||
|
||||
int _u_order;
|
||||
int _v_order;
|
||||
|
||||
typedef pvector<NurbsVertex> Vertices;
|
||||
Vertices _vertices;
|
||||
int _num_u_vertices;
|
||||
int _num_v_vertices;
|
||||
|
||||
bool _u_knots_dirty;
|
||||
bool _v_knots_dirty;
|
||||
typedef vector_float Knots;
|
||||
Knots _u_knots;
|
||||
Knots _v_knots;
|
||||
|
||||
bool _u_basis_dirty;
|
||||
bool _v_basis_dirty;
|
||||
NurbsBasisVector _u_basis;
|
||||
NurbsBasisVector _v_basis;
|
||||
};
|
||||
|
||||
#include "nurbsSurfaceEvaluator.I"
|
||||
|
||||
#endif
|
||||
|
207
panda/src/parametrics/nurbsSurfaceResult.I
Normal file
207
panda/src/parametrics/nurbsSurfaceResult.I
Normal file
@ -0,0 +1,207 @@
|
||||
// Filename: nurbsSurfaceResult.I
|
||||
// Created by: drose (10Oct03)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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: NurbsSurfaceResult::Destructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE NurbsSurfaceResult::
|
||||
~NurbsSurfaceResult() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceResult::get_start_u
|
||||
// Access: Public
|
||||
// Description: Returns the first legal value of u on the surface.
|
||||
// Usually this is 0.0.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float NurbsSurfaceResult::
|
||||
get_start_u() const {
|
||||
return _u_basis.get_start_t();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceResult::get_end_u
|
||||
// Access: Public
|
||||
// Description: Returns the last legal value of u on the surface.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float NurbsSurfaceResult::
|
||||
get_end_u() const {
|
||||
return _u_basis.get_end_t();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceResult::get_start_v
|
||||
// Access: Public
|
||||
// Description: Returns the first legal value of v on the surface.
|
||||
// Usually this is 0.0.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float NurbsSurfaceResult::
|
||||
get_start_v() const {
|
||||
return _v_basis.get_start_t();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceResult::get_end_v
|
||||
// Access: Public
|
||||
// Description: Returns the last legal value of v on the surface.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float NurbsSurfaceResult::
|
||||
get_end_v() const {
|
||||
return _v_basis.get_end_t();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceResult::eval_point
|
||||
// Access: Published
|
||||
// Description: Computes the point on the surface corresponding to the
|
||||
// indicated value in parametric time. Returns true if
|
||||
// the t value is value, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool NurbsSurfaceResult::
|
||||
eval_point(float u, float v, LVecBase3f &point) {
|
||||
int ui = find_u_segment(u);
|
||||
int vi = find_v_segment(v);
|
||||
if (ui == -1 || vi == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
eval_segment_point(ui, vi, _u_basis.scale_t(ui, u), _v_basis.scale_t(vi, v),
|
||||
point);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceResult::eval_normal
|
||||
// Access: Published
|
||||
// Description: Computes the normal to the surface at the indicated
|
||||
// point in parametric time. This normal vector will
|
||||
// not necessarily be normalized, and could be zero.
|
||||
// See also eval_point().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool NurbsSurfaceResult::
|
||||
eval_normal(float u, float v, LVecBase3f &normal) {
|
||||
int ui = find_u_segment(u);
|
||||
int vi = find_v_segment(v);
|
||||
if (ui == -1 || vi == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
eval_segment_normal(ui, vi, _u_basis.scale_t(ui, u), _v_basis.scale_t(vi, v),
|
||||
normal);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceResult::eval_extended_point
|
||||
// Access: Published
|
||||
// Description: Evaluates the surface in n-dimensional space according
|
||||
// to the extended vertices associated with the surface in
|
||||
// the indicated dimension.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float NurbsSurfaceResult::
|
||||
eval_extended_point(float u, float v, int d) {
|
||||
int ui = find_u_segment(u);
|
||||
int vi = find_v_segment(v);
|
||||
if (ui == -1 || vi == -1) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return eval_segment_extended_point(ui, vi, _u_basis.scale_t(ui, u),
|
||||
_v_basis.scale_t(vi, v), d);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceResult::get_num_u_segments
|
||||
// Access: Public
|
||||
// Description: Returns the number of piecewise continuous segments
|
||||
// within the surface in the U direction. This number
|
||||
// is usually not important unless you plan to call
|
||||
// eval_segment_point().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int NurbsSurfaceResult::
|
||||
get_num_u_segments() const {
|
||||
return _u_basis.get_num_segments();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceResult::get_num_v_segments
|
||||
// Access: Public
|
||||
// Description: Returns the number of piecewise continuous segments
|
||||
// within the surface in the V direction. This number
|
||||
// is usually not important unless you plan to call
|
||||
// eval_segment_point().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int NurbsSurfaceResult::
|
||||
get_num_v_segments() const {
|
||||
return _v_basis.get_num_segments();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceResult::get_segment_u
|
||||
// Access: Public
|
||||
// Description: Accepts a u value in the range [0, 1], and assumed to
|
||||
// be relative to the indicated segment (as in
|
||||
// eval_segment_point()), and returns the corresponding
|
||||
// u value in the entire surface (as in eval_point()).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float NurbsSurfaceResult::
|
||||
get_segment_u(int ui, float u) const {
|
||||
return u * (_u_basis.get_to(ui) - _u_basis.get_from(ui)) + _u_basis.get_from(ui);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceResult::get_segment_v
|
||||
// Access: Public
|
||||
// Description: Accepts a v value in the range [0, 1], and assumed to
|
||||
// be relative to the indicated segment (as in
|
||||
// eval_segment_point()), and returns the corresponding
|
||||
// v value in the entire surface (as in eval_point()).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float NurbsSurfaceResult::
|
||||
get_segment_v(int vi, float v) const {
|
||||
return v * (_v_basis.get_to(vi) - _v_basis.get_from(vi)) + _v_basis.get_from(vi);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceResult::verti
|
||||
// Access: Private
|
||||
// Description: An internal function to dereference a 2-d vertex
|
||||
// coordinate pair into a linear list of vertices. This
|
||||
// returns the linear index corresponding to the 2-d
|
||||
// pair.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int NurbsSurfaceResult::
|
||||
verti(int ui, int vi) const {
|
||||
return ui * _num_v_vertices + vi;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceResult::segi
|
||||
// Access: Private
|
||||
// Description: An internal function to dereference a 2-d segment
|
||||
// coordinate pair into a linear list of segments. This
|
||||
// returns the linear index corresponding to the 2-d
|
||||
// pair.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int NurbsSurfaceResult::
|
||||
segi(int ui, int vi) const {
|
||||
return ui * _v_basis.get_num_segments() + vi;
|
||||
}
|
337
panda/src/parametrics/nurbsSurfaceResult.cxx
Normal file
337
panda/src/parametrics/nurbsSurfaceResult.cxx
Normal file
@ -0,0 +1,337 @@
|
||||
// Filename: nurbsSurfaceResult.cxx
|
||||
// Created by: drose (10Oct03)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "nurbsSurfaceResult.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceResult::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.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
NurbsSurfaceResult::
|
||||
NurbsSurfaceResult(const NurbsBasisVector &u_basis,
|
||||
const NurbsBasisVector &v_basis,
|
||||
const LVecBase4f vecs[], const NurbsVertex *verts,
|
||||
int num_u_vertices, int num_v_vertices) :
|
||||
_u_basis(u_basis),
|
||||
_v_basis(v_basis),
|
||||
_verts(verts),
|
||||
_num_u_vertices(num_u_vertices),
|
||||
_num_v_vertices(num_v_vertices)
|
||||
{
|
||||
_last_u_segment = -1;
|
||||
_last_v_segment = -1;
|
||||
int u_order = _u_basis.get_order();
|
||||
int v_order = _v_basis.get_order();
|
||||
int num_u_segments = _u_basis.get_num_segments();
|
||||
int num_v_segments = _v_basis.get_num_segments();
|
||||
int num_segments = num_u_segments * num_v_segments;
|
||||
|
||||
_composed.reserve(num_segments);
|
||||
for (int ui = 0; ui < num_u_segments; ui++) {
|
||||
const LMatrix4f &u_basis_mat = _u_basis.get_basis(ui);
|
||||
|
||||
int un = _u_basis.get_vertex_index(ui);
|
||||
nassertv(un >= 0 && un + u_order - 1 < _num_u_vertices);
|
||||
|
||||
for (int vi = 0; vi < num_v_segments; vi++) {
|
||||
LMatrix4f v_basis_transpose = transpose(_v_basis.get_basis(vi));
|
||||
|
||||
int vn = _v_basis.get_vertex_index(vi);
|
||||
nassertv(vn >= 0 && vn + v_order - 1 < _num_v_vertices);
|
||||
|
||||
// Create four geometry matrices from our (up to) sixteen
|
||||
// involved vertices.
|
||||
LVecBase4f c[4][4];
|
||||
for (int uni = 0; uni < 4; uni++) {
|
||||
for (int vni = 0; vni < 4; vni++) {
|
||||
c[uni][vni] = (uni < u_order && vni < v_order) ?
|
||||
vecs[verti(un + uni, vn + vni)] :
|
||||
LVecBase4f::zero();
|
||||
}
|
||||
}
|
||||
|
||||
LMatrix4f geom_x(c[0][0][0], c[0][1][0], c[0][2][0], c[0][3][0],
|
||||
c[1][0][0], c[1][1][0], c[1][2][0], c[1][3][0],
|
||||
c[2][0][0], c[2][1][0], c[2][2][0], c[2][3][0],
|
||||
c[3][0][0], c[3][1][0], c[3][2][0], c[3][3][0]);
|
||||
|
||||
LMatrix4f geom_y(c[0][0][1], c[0][1][1], c[0][2][1], c[0][3][1],
|
||||
c[1][0][1], c[1][1][1], c[1][2][1], c[1][3][1],
|
||||
c[2][0][1], c[2][1][1], c[2][2][1], c[2][3][1],
|
||||
c[3][0][1], c[3][1][1], c[3][2][1], c[3][3][1]);
|
||||
|
||||
LMatrix4f geom_z(c[0][0][2], c[0][1][2], c[0][2][2], c[0][3][2],
|
||||
c[1][0][2], c[1][1][2], c[1][2][2], c[1][3][2],
|
||||
c[2][0][2], c[2][1][2], c[2][2][2], c[2][3][2],
|
||||
c[3][0][2], c[3][1][2], c[3][2][2], c[3][3][2]);
|
||||
|
||||
LMatrix4f geom_w(c[0][0][3], c[0][1][3], c[0][2][3], c[0][3][3],
|
||||
c[1][0][3], c[1][1][3], c[1][2][3], c[1][3][3],
|
||||
c[2][0][3], c[2][1][3], c[2][2][3], c[2][3][3],
|
||||
c[3][0][3], c[3][1][3], c[3][2][3], c[3][3][3]);
|
||||
|
||||
// And compose these geometry matrices with the basis matrices
|
||||
// to produce a new set of matrices, which will be used to
|
||||
// evaluate the surface.
|
||||
ComposedMats result;
|
||||
result._x = u_basis_mat * geom_x * v_basis_transpose;
|
||||
result._y = u_basis_mat * geom_y * v_basis_transpose;
|
||||
result._z = u_basis_mat * geom_z * v_basis_transpose;
|
||||
result._w = u_basis_mat * geom_w * v_basis_transpose;
|
||||
|
||||
_composed.push_back(result);
|
||||
}
|
||||
}
|
||||
|
||||
nassertv((int)_composed.size() == num_segments);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceResult::eval_segment_point
|
||||
// Access: Published
|
||||
// Description: Evaluates the point on the surface corresponding to the
|
||||
// indicated value in parametric time within the
|
||||
// indicated surface segment. u and v should be in the
|
||||
// range [0, 1].
|
||||
//
|
||||
// The surface is internally represented as a number of
|
||||
// connected (or possibly unconnected) piecewise
|
||||
// continuous segments. The exact number of segments
|
||||
// for a particular surface depends on the knot vector,
|
||||
// and is returned by get_num_segments(). Normally,
|
||||
// eval_point() is used to evaluate a point along the
|
||||
// continuous surface, but when you care more about local
|
||||
// continuity, you can use eval_segment_point() to
|
||||
// evaluate the points along each segment.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NurbsSurfaceResult::
|
||||
eval_segment_point(int ui, int vi, float u, float v, LVecBase3f &point) const {
|
||||
float u2 = u*u;
|
||||
LVecBase4f uvec(u*u2, u2, u, 1.0f);
|
||||
float v2 = v*v;
|
||||
LVecBase4f vvec(v*v2, v2, v, 1.0f);
|
||||
int i = segi(ui, vi);
|
||||
nassertv(i >= 0 && i < (int)_composed.size());
|
||||
|
||||
float weight = vvec.dot(uvec * _composed[i]._w);
|
||||
|
||||
point.set(vvec.dot(uvec * _composed[i]._x) / weight,
|
||||
vvec.dot(uvec * _composed[i]._y) / weight,
|
||||
vvec.dot(uvec * _composed[i]._z) / weight);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceResult::eval_segment_normal
|
||||
// Access: Published
|
||||
// Description: As eval_segment_point, but computes the normal to
|
||||
// the surface at the indicated point. The normal vector
|
||||
// will not necessarily be normalized, and could be
|
||||
// zero.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NurbsSurfaceResult::
|
||||
eval_segment_normal(int ui, int vi, float u, float v, LVecBase3f &normal) const {
|
||||
/*
|
||||
float t2 = t*t;
|
||||
LVecBase4f tvec(t2, t, 1.0f, 0.0f);
|
||||
|
||||
normal.set(tvec.dot(_composed[segment].get_col(0)),
|
||||
tvec.dot(_composed[segment].get_col(1)),
|
||||
tvec.dot(_composed[segment].get_col(2)));
|
||||
*/
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceResult::eval_segment_extended_point
|
||||
// Access: Published
|
||||
// Description: Evaluates the surface in n-dimensional space according
|
||||
// to the extended vertices associated with the surface in
|
||||
// the indicated dimension.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float NurbsSurfaceResult::
|
||||
eval_segment_extended_point(int ui, int vi, float u, float v, int d) const {
|
||||
/*
|
||||
nassertr(segment >= 0 && segment < _basis.get_num_segments(), 0.0f);
|
||||
|
||||
int order = _basis.get_order();
|
||||
int vi = _basis.get_vertex_index(segment);
|
||||
|
||||
LVecBase4f geom;
|
||||
int ci = 0;
|
||||
while (ci < order) {
|
||||
geom[ci] = _verts[vi + ci].get_extended_vertex(d);
|
||||
ci++;
|
||||
}
|
||||
while (ci < 4) {
|
||||
geom[ci] = 0.0f;
|
||||
ci++;
|
||||
}
|
||||
|
||||
const LMatrix4f &basis = _basis.get_basis(segment);
|
||||
|
||||
// Compute matrix * column vector.
|
||||
LVecBase4f composed_geom(basis.get_row(0).dot(geom),
|
||||
basis.get_row(1).dot(geom),
|
||||
basis.get_row(2).dot(geom),
|
||||
basis.get_row(3).dot(geom));
|
||||
|
||||
float t2 = t*t;
|
||||
LVecBase4f tvec(t*t2, t2, t, 1.0f);
|
||||
|
||||
float weight = tvec.dot(_composed[segment].get_col(3));
|
||||
|
||||
float result = tvec.dot(composed_geom) / weight;
|
||||
return result;
|
||||
*/
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceResult::find_u_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 NurbsSurfaceResult::
|
||||
find_u_segment(float u) {
|
||||
// Trivially check the endpoints of the surface.
|
||||
if (u >= get_end_u()) {
|
||||
return _u_basis.get_num_segments() - 1;
|
||||
} else if (u <= get_start_u()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Check the last segment we searched for. Often, two consecutive
|
||||
// requests are for the same segment.
|
||||
if (_last_u_segment != -1 && (u >= _last_u_from && u < _last_u_to)) {
|
||||
return _last_u_segment;
|
||||
}
|
||||
|
||||
// Look for the segment the hard way.
|
||||
int segment = r_find_u_segment(u, 0, _u_basis.get_num_segments() - 1);
|
||||
if (segment != -1) {
|
||||
_last_u_segment = segment;
|
||||
_last_u_from = _u_basis.get_from(segment);
|
||||
_last_u_to = _u_basis.get_to(segment);
|
||||
}
|
||||
return segment;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceResult::r_find_u_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 NurbsSurfaceResult::
|
||||
r_find_u_segment(float u, int top, int bot) const {
|
||||
if (bot < top) {
|
||||
// Not found.
|
||||
return -1;
|
||||
}
|
||||
int mid = (top + bot) / 2;
|
||||
nassertr(mid >= 0 && mid < _u_basis.get_num_segments(), -1);
|
||||
|
||||
float from = _u_basis.get_from(mid);
|
||||
float to = _u_basis.get_to(mid);
|
||||
if (from > u) {
|
||||
// Too high, try lower.
|
||||
return r_find_u_segment(u, top, mid - 1);
|
||||
|
||||
} else if (to <= u) {
|
||||
// Too low, try higher.
|
||||
return r_find_u_segment(u, mid + 1, bot);
|
||||
|
||||
} else {
|
||||
// Here we are!
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceResult::find_v_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 NurbsSurfaceResult::
|
||||
find_v_segment(float v) {
|
||||
// Trivially check the endpoints of the surface.
|
||||
if (v >= get_end_v()) {
|
||||
return _v_basis.get_num_segments() - 1;
|
||||
} else if (v <= get_start_v()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Check the last segment we searched for. Often, two consecutive
|
||||
// requests are for the same segment.
|
||||
if (_last_v_segment != -1 && (v >= _last_v_from && v < _last_v_to)) {
|
||||
return _last_v_segment;
|
||||
}
|
||||
|
||||
// Look for the segment the hard way.
|
||||
int segment = r_find_v_segment(v, 0, _v_basis.get_num_segments() - 1);
|
||||
if (segment != -1) {
|
||||
_last_v_segment = segment;
|
||||
_last_v_from = _v_basis.get_from(segment);
|
||||
_last_v_to = _v_basis.get_to(segment);
|
||||
}
|
||||
return segment;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsSurfaceResult::r_find_v_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 NurbsSurfaceResult::
|
||||
r_find_v_segment(float v, int top, int bot) const {
|
||||
if (bot < top) {
|
||||
// Not found.
|
||||
return -1;
|
||||
}
|
||||
int mid = (top + bot) / 2;
|
||||
nassertr(mid >= 0 && mid < _v_basis.get_num_segments(), -1);
|
||||
|
||||
float from = _v_basis.get_from(mid);
|
||||
float to = _v_basis.get_to(mid);
|
||||
if (from > v) {
|
||||
// Too high, try lower.
|
||||
return r_find_v_segment(v, top, mid - 1);
|
||||
|
||||
} else if (to <= v) {
|
||||
// Too low, try higher.
|
||||
return r_find_v_segment(v, mid + 1, bot);
|
||||
|
||||
} else {
|
||||
// Here we are!
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
|
101
panda/src/parametrics/nurbsSurfaceResult.h
Normal file
101
panda/src/parametrics/nurbsSurfaceResult.h
Normal file
@ -0,0 +1,101 @@
|
||||
// Filename: nurbsSurfaceResult.h
|
||||
// Created by: drose (10Oct03)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 NURBSSURFACERESULT_H
|
||||
#define NURBSSURFACERESULT_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "referenceCount.h"
|
||||
#include "nurbsBasisVector.h"
|
||||
|
||||
class NurbsVertex;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : NurbsSurfaceResult
|
||||
// Description : The result of a NurbsSurfaceEvaluator. This object
|
||||
// represents a surface in a particular coordinate space.
|
||||
// It can return the point and/or normal to the surface
|
||||
// at any point.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA NurbsSurfaceResult : public ReferenceCount {
|
||||
public:
|
||||
NurbsSurfaceResult(const NurbsBasisVector &u_basis,
|
||||
const NurbsBasisVector &v_basis,
|
||||
const LVecBase4f vecs[], const NurbsVertex *verts,
|
||||
int num_u_vertices, int num_v_vertices);
|
||||
|
||||
PUBLISHED:
|
||||
INLINE ~NurbsSurfaceResult();
|
||||
|
||||
INLINE float get_start_u() const;
|
||||
INLINE float get_end_u() const;
|
||||
|
||||
INLINE float get_start_v() const;
|
||||
INLINE float get_end_v() const;
|
||||
|
||||
INLINE bool eval_point(float u, float v, LVecBase3f &point);
|
||||
INLINE bool eval_normal(float u, float v, LVecBase3f &normal);
|
||||
INLINE float eval_extended_point(float u, float v, int d);
|
||||
|
||||
INLINE int get_num_u_segments() const;
|
||||
INLINE int get_num_v_segments() const;
|
||||
void eval_segment_point(int ui, int vi, float u, float v, LVecBase3f &point) const;
|
||||
void eval_segment_normal(int ui, int vi, float u, float v, LVecBase3f &normal) const;
|
||||
float eval_segment_extended_point(int ui, int vi, float u, float v, int d) const;
|
||||
INLINE float get_segment_u(int ui, float u) const;
|
||||
INLINE float get_segment_v(int vi, float v) const;
|
||||
|
||||
private:
|
||||
INLINE int verti(int ui, int vi) const;
|
||||
INLINE int segi(int ui, int vi) const;
|
||||
|
||||
int find_u_segment(float u);
|
||||
int r_find_u_segment(float u, int top, int bot) const;
|
||||
int find_v_segment(float v);
|
||||
int r_find_v_segment(float v, int top, int bot) const;
|
||||
|
||||
NurbsBasisVector _u_basis;
|
||||
NurbsBasisVector _v_basis;
|
||||
const NurbsVertex *_verts;
|
||||
int _num_u_vertices;
|
||||
int _num_v_vertices;
|
||||
|
||||
// We pre-compose the basis matrix and the geometry vectors, so we
|
||||
// have these handy for evaluation. There is one entry in the
|
||||
// _composed for each entry in u_basis._segments *
|
||||
// v_basis._segments.
|
||||
class ComposedMats {
|
||||
public:
|
||||
LMatrix4f _x, _y, _z, _w;
|
||||
};
|
||||
typedef pvector<ComposedMats> ComposedGeom;
|
||||
ComposedGeom _composed;
|
||||
|
||||
|
||||
int _last_u_segment;
|
||||
float _last_u_from;
|
||||
float _last_u_to;
|
||||
int _last_v_segment;
|
||||
float _last_v_from;
|
||||
float _last_v_to;
|
||||
};
|
||||
|
||||
#include "nurbsSurfaceResult.I"
|
||||
|
||||
#endif
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include "parametricCurveDrawer.cxx"
|
||||
#include "nurbsCurveEvaluator.cxx"
|
||||
#include "nurbsCurveResult.cxx"
|
||||
#include "nurbsSurfaceEvaluator.cxx"
|
||||
#include "nurbsSurfaceResult.cxx"
|
||||
#include "nurbsBasisVector.cxx"
|
||||
#include "nurbsVertex.cxx"
|
||||
#include "ropeNode.cxx"
|
||||
|
Loading…
x
Reference in New Issue
Block a user