00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "nurbsCurveEvaluator.h"
00020
00021
00022
00023
00024
00025
00026 NurbsCurveEvaluator::
00027 NurbsCurveEvaluator() {
00028 _order = 4;
00029 _knots_dirty = true;
00030 _basis_dirty = true;
00031 }
00032
00033
00034
00035
00036
00037
00038 NurbsCurveEvaluator::
00039 ~NurbsCurveEvaluator() {
00040 }
00041
00042
00043
00044
00045
00046
00047
00048
00049
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
00065
00066
00067
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
00080
00081
00082
00083
00084
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
00097
00098
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
00111
00112
00113
00114
00115
00116
00117 PT(NurbsCurveResult) NurbsCurveEvaluator::
00118 evaluate(const NodePath &rel_to) const {
00119 if (_basis_dirty) {
00120 ((NurbsCurveEvaluator *)this)->recompute_basis();
00121 }
00122
00123
00124 pvector<LVecBase4f> verts;
00125 get_vertices(verts, rel_to);
00126
00127
00128
00129 return new NurbsCurveResult(_basis, _order, &verts[0], (int)verts.size());
00130 }
00131
00132
00133
00134
00135
00136
00137
00138
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
00159
00160
00161
00162
00163
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
00184
00185
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
00216
00217
00218
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
00235 _basis.append_segment(_order, i - _order, &_knots[i - _order]);
00236 }
00237 }
00238 }
00239
00240 _basis_dirty = false;
00241 }