Panda3D
 All Classes Functions Variables Enumerations
nurbsBasisVector.cxx
1 // Filename: nurbsBasisVector.cxx
2 // Created by: drose (03Dec02)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "nurbsBasisVector.h"
16 
17 ////////////////////////////////////////////////////////////////////
18 // Function: NurbsBasisVector::clear
19 // Access: Public
20 // Description: Removes all the segments from the curve.
21 ////////////////////////////////////////////////////////////////////
23 clear(int order) {
24  _order = order;
25  _segments.clear();
26 }
27 
28 ////////////////////////////////////////////////////////////////////
29 // Function: NurbsBasisVector::append_segment
30 // Access: Public
31 // Description: Computes a NURBS basis for one segment of the curve
32 // and appends it to the set of basis matrices.
33 ////////////////////////////////////////////////////////////////////
35 append_segment(int vertex_index, const PN_stdfloat knots[]) {
36  int i;
37 
38  // Scale the supplied knots to the range 0..1.
39  PN_stdfloat scaled_knots[8];
40  PN_stdfloat min_k = knots[_order - 1];
41  PN_stdfloat max_k = knots[_order];
42 
43  nassertv(min_k != max_k);
44  for (i = 0; i < _order + _order; i++) {
45  scaled_knots[i] = (knots[i] - min_k) / (max_k - min_k);
46  }
47 
48  Segment segment;
49  segment._vertex_index = vertex_index;
50  segment._from = min_k;
51  segment._to = max_k;
52 
53  for (i = 0; i < _order; i++) {
54  LVecBase4 b = nurbs_blending_function(_order, i, _order, scaled_knots);
55  segment._basis.set_col(i, b);
56  }
57 
58  for (i = _order; i < 4; i++) {
59  segment._basis.set_col(i, LVecBase4::zero());
60  }
61 
62  _segments.push_back(segment);
63 }
64 
65 ////////////////////////////////////////////////////////////////////
66 // Function: NurbsBasisVector::transpose
67 // Access: Public
68 // Description: Transposes the basis matrices stored in the vector.
69 ////////////////////////////////////////////////////////////////////
72  Segments::iterator si;
73  for (si = _segments.begin(); si != _segments.end(); ++si) {
74  (*si)._basis.transpose_in_place();
75  }
76 }
77 
78 ////////////////////////////////////////////////////////////////////
79 // Function: NurbsBasisVector::nurbs_blending_function
80 // Access: Private, Static
81 // Description: Recursively computes the appropriate blending
82 // function for the indicated knot vector.
83 ////////////////////////////////////////////////////////////////////
84 LVecBase4 NurbsBasisVector::
85 nurbs_blending_function(int order, int i, int j, const PN_stdfloat knots[]) {
86  // This is doubly recursive. Ick.
87  LVecBase4 r;
88 
89  if (j == 1) {
90  if (i == order - 1 && knots[i] < knots[i + 1]) {
91  r.set(0.0f, 0.0f, 0.0f, 1.0f);
92  } else {
93  r.set(0.0f, 0.0f, 0.0f, 0.0f);
94  }
95 
96  } else {
97  LVecBase4 bi0 = nurbs_blending_function(order, i, j - 1, knots);
98  LVecBase4 bi1 = nurbs_blending_function(order, i + 1, j - 1, knots);
99 
100  PN_stdfloat d0 = knots[i + j - 1] - knots[i];
101  PN_stdfloat d1 = knots[i + j] - knots[i + 1];
102 
103  // First term. Division by zero is defined to equal zero.
104  if (d0 != 0.0f) {
105  if (d1 != 0.0f) {
106  r = bi0 / d0 - bi1 / d1;
107  } else {
108  r = bi0 / d0;
109  }
110 
111  } else if (d1 != 0.0f) {
112  r = - bi1 / d1;
113 
114  } else {
115  r.set(0.0f, 0.0f, 0.0f, 0.0f);
116  }
117 
118  // scale by t.
119  r[0] = r[1];
120  r[1] = r[2];
121  r[2] = r[3];
122  r[3] = 0.0f;
123 
124  // Second term.
125  if (d0 != 0.0f) {
126  if (d1 != 0.0f) {
127  r += bi0 * (- knots[i] / d0) + bi1 * (knots[i + j] / d1);
128  } else {
129  r += bi0 * (- knots[i] / d0);
130  }
131 
132  } else if (d1 != 0.0f) {
133  r += bi1 * (knots[i + j] / d1);
134  }
135  }
136 
137  return r;
138 }
void transpose()
Transposes the basis matrices stored in the vector.
void append_segment(int vertex_index, const PN_stdfloat knots[])
Computes a NURBS basis for one segment of the curve and appends it to the set of basis matrices...
void clear(int order)
Removes all the segments from the curve.
This is the base class for all three-component vectors and points.
Definition: lvecBase4.h:111
static const LVecBase4f & zero()
Returns a zero-length vector.
Definition: lvecBase4.h:492