Panda3D
|
00001 // Filename: nurbsBasisVector.cxx 00002 // Created by: drose (03Dec02) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "nurbsBasisVector.h" 00016 00017 //////////////////////////////////////////////////////////////////// 00018 // Function: NurbsBasisVector::clear 00019 // Access: Public 00020 // Description: Removes all the segments from the curve. 00021 //////////////////////////////////////////////////////////////////// 00022 void NurbsBasisVector:: 00023 clear(int order) { 00024 _order = order; 00025 _segments.clear(); 00026 } 00027 00028 //////////////////////////////////////////////////////////////////// 00029 // Function: NurbsBasisVector::append_segment 00030 // Access: Public 00031 // Description: Computes a NURBS basis for one segment of the curve 00032 // and appends it to the set of basis matrices. 00033 //////////////////////////////////////////////////////////////////// 00034 void NurbsBasisVector:: 00035 append_segment(int vertex_index, const PN_stdfloat knots[]) { 00036 int i; 00037 00038 // Scale the supplied knots to the range 0..1. 00039 PN_stdfloat scaled_knots[8]; 00040 PN_stdfloat min_k = knots[_order - 1]; 00041 PN_stdfloat max_k = knots[_order]; 00042 00043 nassertv(min_k != max_k); 00044 for (i = 0; i < _order + _order; i++) { 00045 scaled_knots[i] = (knots[i] - min_k) / (max_k - min_k); 00046 } 00047 00048 Segment segment; 00049 segment._vertex_index = vertex_index; 00050 segment._from = min_k; 00051 segment._to = max_k; 00052 00053 for (i = 0; i < _order; i++) { 00054 LVecBase4 b = nurbs_blending_function(_order, i, _order, scaled_knots); 00055 segment._basis.set_col(i, b); 00056 } 00057 00058 for (i = _order; i < 4; i++) { 00059 segment._basis.set_col(i, LVecBase4::zero()); 00060 } 00061 00062 _segments.push_back(segment); 00063 } 00064 00065 //////////////////////////////////////////////////////////////////// 00066 // Function: NurbsBasisVector::transpose 00067 // Access: Public 00068 // Description: Transposes the basis matrices stored in the vector. 00069 //////////////////////////////////////////////////////////////////// 00070 void NurbsBasisVector:: 00071 transpose() { 00072 Segments::iterator si; 00073 for (si = _segments.begin(); si != _segments.end(); ++si) { 00074 (*si)._basis.transpose_in_place(); 00075 } 00076 } 00077 00078 //////////////////////////////////////////////////////////////////// 00079 // Function: NurbsBasisVector::nurbs_blending_function 00080 // Access: Private, Static 00081 // Description: Recursively computes the appropriate blending 00082 // function for the indicated knot vector. 00083 //////////////////////////////////////////////////////////////////// 00084 LVecBase4 NurbsBasisVector:: 00085 nurbs_blending_function(int order, int i, int j, const PN_stdfloat knots[]) { 00086 // This is doubly recursive. Ick. 00087 LVecBase4 r; 00088 00089 if (j == 1) { 00090 if (i == order - 1 && knots[i] < knots[i + 1]) { 00091 r.set(0.0f, 0.0f, 0.0f, 1.0f); 00092 } else { 00093 r.set(0.0f, 0.0f, 0.0f, 0.0f); 00094 } 00095 00096 } else { 00097 LVecBase4 bi0 = nurbs_blending_function(order, i, j - 1, knots); 00098 LVecBase4 bi1 = nurbs_blending_function(order, i + 1, j - 1, knots); 00099 00100 PN_stdfloat d0 = knots[i + j - 1] - knots[i]; 00101 PN_stdfloat d1 = knots[i + j] - knots[i + 1]; 00102 00103 // First term. Division by zero is defined to equal zero. 00104 if (d0 != 0.0f) { 00105 if (d1 != 0.0f) { 00106 r = bi0 / d0 - bi1 / d1; 00107 } else { 00108 r = bi0 / d0; 00109 } 00110 00111 } else if (d1 != 0.0f) { 00112 r = - bi1 / d1; 00113 00114 } else { 00115 r.set(0.0f, 0.0f, 0.0f, 0.0f); 00116 } 00117 00118 // scale by t. 00119 r[0] = r[1]; 00120 r[1] = r[2]; 00121 r[2] = r[3]; 00122 r[3] = 0.0f; 00123 00124 // Second term. 00125 if (d0 != 0.0f) { 00126 if (d1 != 0.0f) { 00127 r += bi0 * (- knots[i] / d0) + bi1 * (knots[i + j] / d1); 00128 } else { 00129 r += bi0 * (- knots[i] / d0); 00130 } 00131 00132 } else if (d1 != 0.0f) { 00133 r += bi1 * (knots[i + j] / d1); 00134 } 00135 } 00136 00137 return r; 00138 }