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

panda/src/parametrics/nurbsCurveResult.cxx

Go to the documentation of this file.
00001 // Filename: nurbsCurveResult.cxx
00002 // Created by:  drose (04Dec02)
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 "nurbsCurveResult.h"
00020 
00021 
00022 ////////////////////////////////////////////////////////////////////
00023 //     Function: NurbsCurveResult::Constructor
00024 //       Access: Public
00025 //  Description: The constructor automatically builds up the result as
00026 //               the product of the indicated set of basis matrices
00027 //               and the indicated table of control vertex positions.
00028 ////////////////////////////////////////////////////////////////////
00029 NurbsCurveResult::
00030 NurbsCurveResult(const NurbsMatrixVector &basis, int order,
00031                  const LVecBase4f verts[], int num_vertices) {
00032   _last_segment = -1;
00033 
00034   int num_segments = basis.get_num_segments();
00035   for (int i = 0; i < num_segments; i++) {
00036     int vi = basis.get_vertex_index(i);
00037     nassertv(vi >= 0 && vi < num_vertices);
00038 
00039     // Create a matrix from our (up to) four involved vertices.
00040     LMatrix4f geom;
00041     int ci = 0;
00042     while (ci < order) {
00043       geom.set_row(ci, verts[vi + ci]);
00044       ci++;
00045     }
00046     while (ci < 4) {
00047       geom.set_row(ci, LVecBase4f::zero());
00048       ci++;
00049     }
00050 
00051     // And compose this matrix with the segment to produce a new
00052     // matrix.
00053     _prod.compose_segment(basis, i, geom);
00054   }
00055 }
00056 
00057 ////////////////////////////////////////////////////////////////////
00058 //     Function: NurbsCurveResult::eval_segment_point
00059 //       Access: Published
00060 //  Description: Evaluates the point on the curve corresponding to the
00061 //               indicated value in parametric time within the
00062 //               indicated curve segment.  t should be in the range
00063 //               [0, 1].
00064 //
00065 //               The curve is internally represented as a number of
00066 //               connected (or possibly unconnected) piecewise
00067 //               continuous segments.  The exact number of segments
00068 //               for a particular curve depends on the knot vector,
00069 //               and is returned by get_num_segments().  Normally,
00070 //               eval_point() is used to evaluate a point along the
00071 //               continuous curve, but when you care more about local
00072 //               continuity, you can use eval_segment_point() to
00073 //               evaluate the points along each segment.
00074 ////////////////////////////////////////////////////////////////////
00075 void NurbsCurveResult::
00076 eval_segment_point(int segment, float t, LVecBase3f &point) const {
00077   const LMatrix4f &mat = _prod.get_matrix(segment);
00078 
00079   float t2 = t*t;
00080   LVecBase4f tvec(t*t2, t2, t, 1.0f);
00081   LVecBase4f r = tvec * mat;
00082   point.set(r[0] / r[3], r[1] / r[3], r[2] / r[3]);
00083 }
00084 
00085 ////////////////////////////////////////////////////////////////////
00086 //     Function: NurbsCurveResult::eval_segment_tangent
00087 //       Access: Published
00088 //  Description: As eval_segment_point, but computes the tangent to
00089 //               the curve at the indicated point.  The tangent vector
00090 //               will not necessarily be normalized, and could be
00091 //               zero, particularly at the endpoints.
00092 ////////////////////////////////////////////////////////////////////
00093 void NurbsCurveResult::
00094 eval_segment_tangent(int segment, float t, LVecBase3f &tangent) const {
00095   const LMatrix4f &mat = _prod.get_matrix(segment);
00096 
00097   float t2 = t*t;
00098   LVecBase4f tvec(t2, t, 1.0f, 0.0f);
00099   LVecBase4f r = tvec * mat;
00100   tangent.set(r[0], r[1], r[2]);
00101 }
00102 
00103 ////////////////////////////////////////////////////////////////////
00104 //     Function: NurbsCurveResult::find_segment
00105 //       Access: Private
00106 //  Description: Returns the index of the segment that contains the
00107 //               indicated value of t, or -1 if no segment contains
00108 //               this value.
00109 ////////////////////////////////////////////////////////////////////
00110 int NurbsCurveResult::
00111 find_segment(float t) {
00112   // Trivially check the endpoints of the curve.
00113   if (t >= get_end_t()) {
00114     return _prod.get_num_segments() - 1;
00115   } else if (t <= get_start_t()) {
00116     return 0;
00117   }
00118 
00119   // Check the last segment we searched for.  Often, two consecutive
00120   // requests are for the same segment.
00121   if (_last_segment != -1 && (t >= _last_from && t < _last_to)) {
00122     return _last_segment;
00123   }
00124 
00125   // Look for the segment the hard way.
00126   int segment = r_find_segment(t, 0, _prod.get_num_segments() - 1);
00127   if (segment != -1) {
00128     _last_segment = segment;
00129     _last_from = _prod.get_from(segment);
00130     _last_to = _prod.get_to(segment);
00131   }
00132   return segment;
00133 }
00134 
00135 ////////////////////////////////////////////////////////////////////
00136 //     Function: NurbsCurveResult::r_find_segment
00137 //       Access: Private
00138 //  Description: Recursively searches for the segment that contains
00139 //               the indicated value of t by performing a binary
00140 //               search.  This assumes the segments are stored in
00141 //               increasing order of t, and they don't overlap.
00142 ////////////////////////////////////////////////////////////////////
00143 int NurbsCurveResult::
00144 r_find_segment(float t, int top, int bot) const {
00145   if (bot < top) {
00146     // Not found.
00147     return -1;
00148   }
00149   int mid = (top + bot) / 2;
00150   nassertr(mid >= 0 && mid < _prod.get_num_segments(), -1);
00151 
00152   float from = _prod.get_from(mid);
00153   float to = _prod.get_to(mid);
00154   if (from > t) {
00155     // Too high, try lower.
00156     return r_find_segment(t, top, mid - 1);
00157 
00158   } else if (to <= t) {
00159     // Too low, try higher.
00160     return r_find_segment(t, mid + 1, bot);
00161 
00162   } else {
00163     // Here we are!
00164     return mid;
00165   }
00166 }

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