00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "piecewiseCurve.h"
00020
00021 #include "config_parametrics.h"
00022 #include "hermiteCurve.h"
00023
00024 #include <datagram.h>
00025 #include <datagramIterator.h>
00026 #include <bamWriter.h>
00027 #include <bamReader.h>
00028
00029 TypeHandle CubicCurveseg::_type_handle;
00030
00031
00032
00033
00034
00035
00036 CubicCurveseg::
00037 CubicCurveseg() {
00038 }
00039
00040
00041
00042
00043
00044
00045
00046 CubicCurveseg::
00047 CubicCurveseg(const LMatrix4f &basis) {
00048 Bx = basis.get_col(0);
00049 By = basis.get_col(1);
00050 Bz = basis.get_col(2);
00051 Bw = basis.get_col(3);
00052 rational = true;
00053 }
00054
00055
00056
00057
00058
00059
00060
00061 CubicCurveseg::
00062 CubicCurveseg(const BezierSeg &seg) {
00063 bezier_basis(seg);
00064 }
00065
00066
00067
00068
00069
00070
00071
00072
00073 CubicCurveseg::
00074 CubicCurveseg(int order, const float knots[], const LVecBase4f cvs[]) {
00075 nurbs_basis(order, knots, cvs);
00076 }
00077
00078
00079
00080
00081
00082
00083 CubicCurveseg::
00084 ~CubicCurveseg() {
00085 }
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 bool CubicCurveseg::
00096 get_point(float t, LVecBase3f &point) const {
00097 float t_sqrd = t*t;
00098 evaluate_point(LVecBase4f(t*t_sqrd, t_sqrd, t, 1.0f), point);
00099 return true;
00100 }
00101
00102
00103
00104
00105
00106
00107
00108 bool CubicCurveseg::
00109 get_tangent(float t, LVecBase3f &tangent) const {
00110 evaluate_vector(LVecBase4f(3.0f*t*t, 2.0f*t, 1.0f, 0.0f), tangent);
00111 return true;
00112 }
00113
00114
00115
00116
00117
00118
00119
00120 bool CubicCurveseg::
00121 get_pt(float t, LVecBase3f &point, LVecBase3f &tangent) const {
00122 float t_sqrd=t*t;
00123 evaluate_point(LVecBase4f(t*t_sqrd, t_sqrd, t, 1.0f), point);
00124 evaluate_vector(LVecBase4f(3.0f*t_sqrd, t+t, 1.0f, 0.0f), tangent);
00125 return true;
00126 }
00127
00128
00129
00130
00131
00132
00133
00134 bool CubicCurveseg::
00135 get_2ndtangent(float t, LVecBase3f &tangent2) const {
00136 evaluate_vector(LVecBase4f(6.0f*t, 2.0f, 0.0f, 0.0f), tangent2);
00137 return true;
00138 }
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 void CubicCurveseg::
00149 hermite_basis(const HermiteCurveCV &cv0,
00150 const HermiteCurveCV &cv1,
00151 float tlength) {
00152 static LMatrix4f
00153 Mh( 2.0f, -3.0f, 0.0f, 1.0f,
00154 -2.0f, 3.0f, 0.0f, 0.0f,
00155 1.0f, -2.0f, 1.0f, 0.0f,
00156 1.0f, -1.0f, 0.0f, 0.0f);
00157
00158 LVecBase4f Gx(cv0._p[0], cv1._p[0],
00159 cv0._out[0]*tlength, cv1._in[0]*tlength);
00160 LVecBase4f Gy(cv0._p[1], cv1._p[1],
00161 cv0._out[1]*tlength, cv1._in[1]*tlength);
00162 LVecBase4f Gz(cv0._p[2], cv1._p[2],
00163 cv0._out[2]*tlength, cv1._in[2]*tlength);
00164
00165 Bx = Gx * Mh;
00166 By = Gy * Mh;
00167 Bz = Gz * Mh;
00168 rational = false;
00169 }
00170
00171
00172
00173
00174
00175
00176
00177
00178 void CubicCurveseg::
00179 bezier_basis(const BezierSeg &seg) {
00180 static LMatrix4f
00181 Mb(-1.0f, 3.0f, -3.0f, 1.0f,
00182 3.0f, -6.0f, 3.0f, 0.0f,
00183 -3.0f, 3.0f, 0.0f, 0.0f,
00184 1.0f, 0.0f, 0.0f, 0.0f);
00185
00186 LVecBase4f Gx(seg._v[0][0], seg._v[1][0], seg._v[2][0], seg._v[3][0]);
00187 LVecBase4f Gy(seg._v[0][1], seg._v[1][1], seg._v[2][1], seg._v[3][1]);
00188 LVecBase4f Gz(seg._v[0][2], seg._v[1][2], seg._v[2][2], seg._v[3][2]);
00189
00190 Bx = Gx * Mb;
00191 By = Gy * Mb;
00192 Bz = Gz * Mb;
00193 rational = false;
00194 }
00195
00196 static LVecBase4f
00197 nurbs_blending_function(int order, int i, int j,
00198 const float knots[]) {
00199
00200 LVecBase4f r;
00201
00202 if (j==1) {
00203 if (i==order-1 && knots[i] < knots[i+1]) {
00204 r.set(0.0f, 0.0f, 0.0f, 1.0f);
00205 } else {
00206 r.set(0.0f, 0.0f, 0.0f, 0.0f);
00207 }
00208
00209 } else {
00210 LVecBase4f bi0 = nurbs_blending_function(order, i, j-1, knots);
00211 LVecBase4f bi1 = nurbs_blending_function(order, i+1, j-1, knots);
00212
00213 float d0 = knots[i+j-1] - knots[i];
00214 float d1 = knots[i+j] - knots[i+1];
00215
00216
00217 if (d0 != 0.0f) {
00218 if (d1 != 0.0f) {
00219 r = bi0 / d0 - bi1 / d1;
00220 } else {
00221 r = bi0 / d0;
00222 }
00223
00224 } else if (d1 != 0.0f) {
00225 r = - bi1 / d1;
00226
00227 } else {
00228 r.set(0.0f, 0.0f, 0.0f, 0.0f);
00229 }
00230
00231
00232 r[0] = r[1];
00233 r[1] = r[2];
00234 r[2] = r[3];
00235 r[3] = 0.0f;
00236
00237
00238 if (d0 != 0.0f) {
00239 if (d1 != 0.0f) {
00240 r += bi0 * (- knots[i] / d0) + bi1 * (knots[i+j] / d1);
00241 } else {
00242 r += bi0 * (- knots[i] / d0);
00243 }
00244
00245 } else if (d1 != 0.0f) {
00246 r += bi1 * (knots[i+j] / d1);
00247 }
00248 }
00249
00250 return r;
00251 }
00252
00253 void
00254 compute_nurbs_basis(int order,
00255 const float knots_in[],
00256 LMatrix4f &basis) {
00257 int i;
00258
00259
00260 float knots[8];
00261 float mink = knots_in[order-1];
00262 float maxk = knots_in[order];
00263
00264 if (mink==maxk) {
00265
00266 parametrics_cat->warning()
00267 << "Trivial NURBS curve specified." << endl;
00268 memset((void *)&basis, 0, sizeof(LMatrix4f));
00269 return;
00270 }
00271
00272 for (i = 0; i<2*order; i++) {
00273 knots[i] = (knots_in[i] - mink) / (maxk-mink);
00274 }
00275
00276
00277 LVecBase4f b[4];
00278 for (i = 0; i<order; i++) {
00279 b[i] = nurbs_blending_function(order, i, order, knots);
00280 }
00281
00282 for (i = 0; i<order; i++) {
00283 basis.set_row(i, b[i]);
00284 }
00285
00286 for (i=order; i<4; i++) {
00287 basis.set_row(i, LVecBase4f::zero());
00288 }
00289 }
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 void CubicCurveseg::
00302 nurbs_basis(int order, const float knots[], const LVecBase4f cvs[]) {
00303 assert(order>=1 && order<=4);
00304
00305 LMatrix4f B;
00306 compute_nurbs_basis(order, knots, B);
00307
00308
00309
00310 LVecBase4f c[4];
00311 for (int i = 0; i < 4; i++) {
00312 c[i] = (i<order) ? cvs[i] : LVecBase4f(0.0f, 0.0f, 0.0f, 0.0f);
00313 }
00314
00315 Bx = LVecBase4f(c[0][0], c[1][0], c[2][0], c[3][0]) * B;
00316 By = LVecBase4f(c[0][1], c[1][1], c[2][1], c[3][1]) * B;
00317 Bz = LVecBase4f(c[0][2], c[1][2], c[2][2], c[3][2]) * B;
00318 Bw = LVecBase4f(c[0][3], c[1][3], c[2][3], c[3][3]) * B;
00319
00320 rational = true;
00321 }
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331 bool CubicCurveseg::
00332 get_bezier_seg(BezierSeg &seg) const {
00333 static LMatrix4f
00334 Mbi(0.0f, 0.0f, 0.0f, 1.0f,
00335 0.0f, 0.0f, 1.0f/3.0f, 1.0f,
00336 0.0f, 1.0f/3.0f, 2.0f/3.0f, 1.0f,
00337 1.0f, 1.0f, 1.0f, 1.0f);
00338
00339 LVecBase4f Gx = Bx * Mbi;
00340 LVecBase4f Gy = By * Mbi;
00341 LVecBase4f Gz = Bz * Mbi;
00342
00343 if (rational) {
00344 LVecBase4f Gw = Bw * Mbi;
00345 seg._v[0].set(Gx[0]/Gw[0], Gy[0]/Gw[0], Gz[0]/Gw[0]);
00346 seg._v[1].set(Gx[1]/Gw[1], Gy[1]/Gw[1], Gz[1]/Gw[1]);
00347 seg._v[2].set(Gx[2]/Gw[2], Gy[2]/Gw[2], Gz[2]/Gw[2]);
00348 seg._v[3].set(Gx[3]/Gw[3], Gy[3]/Gw[3], Gz[3]/Gw[3]);
00349 } else {
00350 seg._v[0].set(Gx[0], Gy[0], Gz[0]);
00351 seg._v[1].set(Gx[1], Gy[1], Gz[1]);
00352 seg._v[2].set(Gx[2], Gy[2], Gz[2]);
00353 seg._v[3].set(Gx[3], Gy[3], Gz[3]);
00354 }
00355
00356 return true;
00357 }
00358
00359
00360 inline LVecBase4f
00361 col_mult(const LMatrix4f &M, const LVecBase4f &v) {
00362 return LVecBase4f(M(0,0)*v[0] + M(0,1)*v[1] + M(0,2)*v[2] + M(0,3)*v[3],
00363 M(1,0)*v[0] + M(1,1)*v[1] + M(1,2)*v[2] + M(1,3)*v[3],
00364 M(2,0)*v[0] + M(2,1)*v[1] + M(2,2)*v[2] + M(2,3)*v[3],
00365 M(3,0)*v[0] + M(3,1)*v[1] + M(3,2)*v[2] + M(3,3)*v[3]);
00366 }
00367
00368
00369
00370
00371
00372
00373
00374 static bool
00375 compute_seg_col(int c,
00376 int rtype, float t, const LVecBase4f &v,
00377 const LMatrix4f &B,
00378 const LMatrix4f &Bi,
00379 const LMatrix4f &G,
00380 const LMatrix4f &GB,
00381 LMatrix4f &T, LMatrix4f &P) {
00382 bool keep_orig = ((rtype & RT_KEEP_ORIG) != 0);
00383
00384 if (parametrics_cat.is_debug()) {
00385 parametrics_cat.debug()
00386 << "Computing col " << c << " type " << (rtype & RT_BASE_TYPE)
00387 << " at " << t << " keep_orig = " << keep_orig
00388 << " v = " << v << "\n";
00389 }
00390
00391 switch (rtype & RT_BASE_TYPE) {
00392
00393
00394 float t_sqrd,t_cubed;
00395
00396 case RT_POINT:
00397 t_sqrd = t*t;
00398 t_cubed = t_sqrd*t;
00399 T.set_col(c, LVecBase4f(t_cubed, t_sqrd, t, 1.0f));
00400 if (keep_orig) {
00401 LVecBase4f vec(t_cubed, t_sqrd, t, 1.0f);
00402 LVecBase4f ov = col_mult(GB, vec);
00403 if (parametrics_cat.is_debug()) {
00404 parametrics_cat.debug()
00405 << "orig point = " << ov << "\n";
00406 }
00407 P.set_col(c, ov);
00408 } else {
00409 P.set_col(c, v);
00410 }
00411 break;
00412
00413
00414
00415 case RT_TANGENT:
00416 t_sqrd = t*t;
00417 T.set_col(c, LVecBase4f(3.0f*t_sqrd, t+t, 1.0f, 0.0f));
00418 if (keep_orig) {
00419 LVecBase4f vec(3.0f*t_sqrd, t+t, 1.0f, 0.0f);
00420 LVecBase4f ov = col_mult(GB, vec);
00421 if (parametrics_cat.is_debug()) {
00422 parametrics_cat.debug()
00423 << "Matrix is:\n";
00424 GB.write(parametrics_cat.debug(false), 2);
00425 parametrics_cat.debug(false)
00426 << "vector is " << vec << "\n"
00427 << "orig tangent = " << ov << "\n";
00428 }
00429 P.set_col(c, ov);
00430 } else {
00431 P.set_col(c, v);
00432 }
00433 break;
00434
00435
00436
00437 case RT_CV:
00438 T.set_col(c, Bi.get_col(c));
00439 if (keep_orig) {
00440 if (parametrics_cat.is_debug()) {
00441 parametrics_cat.debug()
00442 << "orig CV = " << G.get_col(c) << "\n";
00443 }
00444 P.set_col(c, G.get_col(c));
00445 } else {
00446 P.set_col(c, v);
00447 }
00448 break;
00449
00450 default:
00451 cerr << "Invalid rebuild type in compute_seg\n";
00452 return false;
00453 }
00454
00455 return true;
00456 }
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509 bool CubicCurveseg::
00510 compute_seg(int rtype0, float t0, const LVecBase4f &v0,
00511 int rtype1, float t1, const LVecBase4f &v1,
00512 int rtype2, float t2, const LVecBase4f &v2,
00513 int rtype3, float t3, const LVecBase4f &v3,
00514 const LMatrix4f &B,
00515 const LMatrix4f &Bi,
00516 LMatrix4f &G) {
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536 LMatrix4f T, P, GB;
00537
00538
00539
00540 if ((rtype0 | rtype1 | rtype2 | rtype3) & RT_KEEP_ORIG) {
00541 GB = G * B;
00542 }
00543
00544 if (! (compute_seg_col(0, rtype0, t0, v0, B, Bi, G, GB, T, P) &&
00545 compute_seg_col(1, rtype1, t1, v1, B, Bi, G, GB, T, P) &&
00546 compute_seg_col(2, rtype2, t2, v2, B, Bi, G, GB, T, P) &&
00547 compute_seg_col(3, rtype3, t3, v3, B, Bi, G, GB, T, P))) {
00548 return false;
00549 }
00550
00551 LMatrix4f Ti;
00552 Ti = invert(T);
00553
00554
00555
00556
00557
00558
00559
00560
00561 G = P * Ti * Bi;
00562
00563 return true;
00564 }
00565
00566
00567
00568
00569
00570
00571
00572 void CubicCurveseg::
00573 register_with_read_factory() {
00574 BamReader::get_factory()->register_factory(get_class_type(), make_CubicCurveseg);
00575 }
00576
00577
00578
00579
00580
00581
00582 TypedWritable *CubicCurveseg::
00583 make_CubicCurveseg(const FactoryParams ¶ms) {
00584 CubicCurveseg *me = new CubicCurveseg;
00585 DatagramIterator scan;
00586 BamReader *manager;
00587
00588 parse_params(params, scan, manager);
00589 me->fillin(scan, manager);
00590 return me;
00591 }
00592
00593
00594
00595
00596
00597
00598
00599 void CubicCurveseg::
00600 write_datagram(BamWriter *manager, Datagram &me) {
00601 ParametricCurve::write_datagram(manager, me);
00602
00603 Bx.write_datagram(me);
00604 By.write_datagram(me);
00605 Bz.write_datagram(me);
00606 Bw.write_datagram(me);
00607 me.add_bool(rational);
00608 }
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618 void CubicCurveseg::
00619 fillin(DatagramIterator &scan, BamReader *manager) {
00620 ParametricCurve::fillin(scan, manager);
00621
00622 Bx.read_datagram(scan);
00623 By.read_datagram(scan);
00624 Bz.read_datagram(scan);
00625 Bw.read_datagram(scan);
00626 rational = scan.get_bool();
00627 }