Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/parametrics/nurbsCurveEvaluator.cxx

Go to the documentation of this file.
00001 // Filename: nurbsCurveEvaluator.cxx
00002 // Created by:  drose (03Dec02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "nurbsCurveEvaluator.h"
00020 
00021 ////////////////////////////////////////////////////////////////////
00022 //     Function: NurbsCurveEvaluator::Constructor
00023 //       Access: Published
00024 //  Description:
00025 ////////////////////////////////////////////////////////////////////
00026 NurbsCurveEvaluator::
00027 NurbsCurveEvaluator() {
00028   _order = 4;
00029   _knots_dirty = true;
00030   _basis_dirty = true;
00031 }
00032 
00033 ////////////////////////////////////////////////////////////////////
00034 //     Function: NurbsCurveEvaluator::Destructor
00035 //       Access: Published
00036 //  Description:
00037 ////////////////////////////////////////////////////////////////////
00038 NurbsCurveEvaluator::
00039 ~NurbsCurveEvaluator() {
00040 }
00041 
00042 ////////////////////////////////////////////////////////////////////
00043 //     Function: NurbsCurveEvaluator::reset
00044 //       Access: Published
00045 //  Description: Resets all the vertices and knots to their default
00046 //               values, and sets the curve up with the indicated
00047 //               number of vertices.  You must then call set_vertex()
00048 //               repeatedly to fill in all of the vertex values
00049 //               appropriately.
00050 ////////////////////////////////////////////////////////////////////
00051 void NurbsCurveEvaluator::
00052 reset(int num_vertices) {
00053   _vertices.clear();
00054   _vertices.reserve(num_vertices);
00055 
00056   for (int i = 0; i < num_vertices; i++) {
00057     _vertices.push_back(NurbsVertex());
00058   }
00059   _knots_dirty = true;
00060   _basis_dirty = true;
00061 }
00062 
00063 ////////////////////////////////////////////////////////////////////
00064 //     Function: NurbsCurveEvaluator::get_vertex_space
00065 //       Access: Published
00066 //  Description: Returns the coordinate space of the nth control
00067 //               vertex of the curve, expressed as a NodePath.
00068 ////////////////////////////////////////////////////////////////////
00069 NodePath NurbsCurveEvaluator::
00070 get_vertex_space(int i, const NodePath &rel_to) const {
00071 #ifndef NDEBUG
00072   static NodePath empty_node_path;
00073   nassertr(i >= 0 && i < (int)_vertices.size(), empty_node_path);
00074 #endif
00075   return _vertices[i].get_space(rel_to);
00076 }
00077 
00078 ////////////////////////////////////////////////////////////////////
00079 //     Function: NurbsCurveEvaluator::set_knot
00080 //       Access: Published
00081 //  Description: Sets the value of the nth knot.  Each knot value
00082 //               should be greater than or equal to the preceding
00083 //               value.  If no knot values are set, a default knot
00084 //               vector is supplied.
00085 ////////////////////////////////////////////////////////////////////
00086 void NurbsCurveEvaluator::
00087 set_knot(int i, float knot) {
00088   if (_knots_dirty) {
00089     recompute_knots();
00090   }
00091   nassertv(i >= 0 && i < (int)_knots.size());
00092   _knots[i] = knot;
00093 }
00094 
00095 ////////////////////////////////////////////////////////////////////
00096 //     Function: NurbsCurveEvaluator::get_knot
00097 //       Access: Published
00098 //  Description: Returns the value of the nth knot.
00099 ////////////////////////////////////////////////////////////////////
00100 float NurbsCurveEvaluator::
00101 get_knot(int i) const {
00102   if (_knots_dirty) {
00103     ((NurbsCurveEvaluator *)this)->recompute_knots();
00104   }
00105   nassertr(i >= 0 && i < (int)_knots.size(), 0.0f);
00106   return _knots[i];
00107 }
00108 
00109 ////////////////////////////////////////////////////////////////////
00110 //     Function: NurbsCurveEvaluator::evaluate
00111 //       Access: Published
00112 //  Description: Returns a NurbsCurveResult object that represents the
00113 //               result of applying the knots to all of the current
00114 //               values of the vertices, transformed into the
00115 //               indicated coordinate space.
00116 ////////////////////////////////////////////////////////////////////
00117 PT(NurbsCurveResult) NurbsCurveEvaluator::
00118 evaluate(const NodePath &rel_to) const {
00119   if (_basis_dirty) {
00120     ((NurbsCurveEvaluator *)this)->recompute_basis();
00121   }
00122 
00123   // First, transform the vertices as appropriate.
00124   pvector<LVecBase4f> verts;
00125   get_vertices(verts, rel_to);
00126 
00127   // And apply those transformed vertices to the basis matrices to
00128   // derive the result.
00129   return new NurbsCurveResult(_basis, _order, &verts[0], (int)verts.size());
00130 }
00131 
00132 ////////////////////////////////////////////////////////////////////
00133 //     Function: NurbsCurveEvaluator::get_vertices
00134 //       Access: Public
00135 //  Description: Fills the indicated vector with the set of vertices
00136 //               in the curve, transformed to the given space.  This
00137 //               flavor returns the vertices in 4-dimensional
00138 //               homogenous space.
00139 ////////////////////////////////////////////////////////////////////
00140 void NurbsCurveEvaluator::
00141 get_vertices(pvector<LVecBase4f> &verts, const NodePath &rel_to) const {
00142   int num_vertices = (int)_vertices.size();
00143   verts.reserve(verts.size() + num_vertices);
00144   int vi;
00145   for (vi = 0; vi < num_vertices; vi++) {
00146     NodePath space = _vertices[vi].get_space(rel_to);
00147     const LVecBase4f &vertex = _vertices[vi].get_vertex();
00148     if (space.is_empty()) {
00149       verts.push_back(vertex);
00150     } else {
00151       const LMatrix4f &mat = space.get_mat(rel_to);
00152       verts.push_back(vertex * mat);
00153     }
00154   }
00155 }
00156 
00157 ////////////////////////////////////////////////////////////////////
00158 //     Function: NurbsCurveEvaluator::get_vertices
00159 //       Access: Public
00160 //  Description: Fills the indicated vector with the set of vertices
00161 //               in the curve, transformed to the given space.  This
00162 //               flavor returns the vertices in 4-dimensional
00163 //               homogenous space.
00164 ////////////////////////////////////////////////////////////////////
00165 void NurbsCurveEvaluator::
00166 get_vertices(pvector<LPoint3f> &verts, const NodePath &rel_to) const {
00167   int num_vertices = (int)_vertices.size();
00168   verts.reserve(verts.size() + num_vertices);
00169   int vi;
00170   for (vi = 0; vi < num_vertices; vi++) {
00171     const NodePath &space = _vertices[vi].get_space(rel_to);
00172     LVecBase4f vertex = _vertices[vi].get_vertex();
00173     if (!space.is_empty()) {
00174       const LMatrix4f &mat = space.get_mat(rel_to);
00175       vertex = vertex * mat;
00176     }
00177     LPoint3f v3(vertex[0] / vertex[3], vertex[1] / vertex[3], vertex[2] / vertex[3]);
00178     verts.push_back(v3);
00179   }
00180 }
00181 
00182 ////////////////////////////////////////////////////////////////////
00183 //     Function: NurbsCurveEvaluator::recompute_knots
00184 //       Access: Private
00185 //  Description: Creates a default knot vector.
00186 ////////////////////////////////////////////////////////////////////
00187 void NurbsCurveEvaluator::
00188 recompute_knots() {
00189   _knots.clear();
00190   int num_knots = get_num_knots();
00191   _knots.reserve(num_knots);
00192 
00193   float value = 0.0f;
00194 
00195   int i = 0;
00196   while (i < _order) {
00197     _knots.push_back(value);
00198     i++;
00199   }
00200   while (i < num_knots - _order) {
00201     value += 1.0f;
00202     _knots.push_back(value);
00203     i++;
00204   }
00205   value += 1.0f;
00206   while (i < num_knots) {
00207     _knots.push_back(value);
00208     i++;
00209   }
00210 
00211   _knots_dirty = false;
00212 }
00213 
00214 ////////////////////////////////////////////////////////////////////
00215 //     Function: NurbsCurveEvaluator::recompute_basis
00216 //       Access: Private
00217 //  Description: Recomputes the basis matrices according to the knot
00218 //               vector.
00219 ////////////////////////////////////////////////////////////////////
00220 void NurbsCurveEvaluator::
00221 recompute_basis() {
00222   if (_knots_dirty) {
00223     ((NurbsCurveEvaluator *)this)->recompute_knots();
00224   }
00225 
00226   _basis.clear();
00227   if ((int)_vertices.size() > _order - 1) {
00228     int min_knot = _order;
00229     int max_knot = (int)_vertices.size() + 1;
00230     
00231     for (int i = min_knot; i <= max_knot; i++) {
00232       nassertv(i - 1 >= 0 && i < (int)_knots.size());
00233       if (_knots[i - 1] < _knots[i]) {
00234         // Here's a non-empty segment.
00235         _basis.append_segment(_order, i - _order, &_knots[i - _order]);
00236       }
00237     }
00238   }
00239 
00240   _basis_dirty = false;
00241 }

Generated on Fri May 2 00:40:45 2003 for Panda by doxygen1.3