Panda3D
|
00001 // Filename: hermiteCurve.cxx 00002 // Created by: drose (27Feb98) 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 "pandabase.h" 00016 #include "hermiteCurve.h" 00017 #include "config_parametrics.h" 00018 #include "luse.h" 00019 00020 #include "indent.h" 00021 #include "datagram.h" 00022 #include "datagramIterator.h" 00023 #include "bamWriter.h" 00024 #include "bamReader.h" 00025 00026 #include <math.h> 00027 00028 TypeHandle HermiteCurve::_type_handle; 00029 00030 static const LVecBase3 zerovec_3 = LVecBase3(0.0f, 0.0f, 0.0f); 00031 // This is returned occasionally from some of the functions, and is 00032 // used from time to time as an initializer. 00033 00034 00035 //////////////////////////////////////////////////////////////////// 00036 // Function: show_vec3 00037 // Description: This function writes a LVecBase3, with a specified 00038 // number of significant dimensions. 00039 //////////////////////////////////////////////////////////////////// 00040 static ostream & 00041 show_vec3(ostream &out, int indent_level, const LVecBase3 &v, 00042 int num_dimensions) { 00043 indent(out, indent_level) << v[0]; 00044 for (int i = 1; i<num_dimensions; i++) { 00045 out << " " << v[i]; 00046 } 00047 return out; 00048 } 00049 00050 //////////////////////////////////////////////////////////////////// 00051 // Function: HermiteCurveCV::constructor 00052 // Access: Public 00053 // Description: 00054 //////////////////////////////////////////////////////////////////// 00055 HermiteCurveCV:: 00056 HermiteCurveCV() { 00057 } 00058 00059 00060 //////////////////////////////////////////////////////////////////// 00061 // Function: HermiteCurveCV::copy_constructor 00062 // Access: Public 00063 // Description: 00064 //////////////////////////////////////////////////////////////////// 00065 HermiteCurveCV:: 00066 HermiteCurveCV(const HermiteCurveCV &c) : 00067 _p(c._p), _in(c._in), _out(c._out), 00068 _type(c._type), _name(c._name) 00069 { 00070 } 00071 00072 00073 //////////////////////////////////////////////////////////////////// 00074 // Function: HermiteCurveCV::destructor 00075 // Access: Public 00076 // Description: 00077 //////////////////////////////////////////////////////////////////// 00078 HermiteCurveCV:: 00079 ~HermiteCurveCV() { 00080 } 00081 00082 00083 00084 //////////////////////////////////////////////////////////////////// 00085 // Function: HermiteCurveCV::set_in 00086 // Access: Public 00087 // Description: Sets the CV's in tangent. 00088 //////////////////////////////////////////////////////////////////// 00089 void HermiteCurveCV:: 00090 set_in(const LVecBase3 &in) { 00091 _in = in; 00092 /* 00093 PN_stdfloat l; 00094 switch (_type) { 00095 case HC_G1: 00096 l = _in.length(); 00097 if (l!=0.0f) { 00098 _out = _in * _out.length() / l; 00099 } 00100 break; 00101 00102 case HC_SMOOTH: 00103 _out = _in; 00104 break; 00105 } 00106 */ 00107 } 00108 00109 00110 //////////////////////////////////////////////////////////////////// 00111 // Function: HermiteCurveCV::set_out 00112 // Access: Public 00113 // Description: Sets the CV's out tangent. 00114 //////////////////////////////////////////////////////////////////// 00115 void HermiteCurveCV:: 00116 set_out(const LVecBase3 &out) { 00117 _out = out; 00118 /* 00119 PN_stdfloat l; 00120 switch (_type) { 00121 case HC_G1: 00122 l = _out.length(); 00123 if (l!=0.0f) { 00124 _in = _out * _in.length() / l; 00125 } 00126 break; 00127 00128 case HC_SMOOTH: 00129 _in = _out; 00130 break; 00131 } 00132 */ 00133 } 00134 00135 00136 //////////////////////////////////////////////////////////////////// 00137 // Function: HermiteCurveCV::set_type 00138 // Access: Public 00139 // Description: Sets the continuity type of the CV. Values may be 00140 // HC_CUT, indicating a discontinous break in the curve, 00141 // HC_FREE, for unconstrained in and out tangents, 00142 // HC_G1, for in and out tangents constrained to be 00143 // collinear, and HC_SMOOTH, for in and out tangents 00144 // constrained to be equal. Other than HC_CUT, these 00145 // are for documentation only; setting this has no 00146 // direct effect on the tangents. 00147 //////////////////////////////////////////////////////////////////// 00148 void HermiteCurveCV:: 00149 set_type(int type) { 00150 _type = type; 00151 /* 00152 switch (_type) { 00153 case HC_G1: 00154 _out = _out.length() * _in; 00155 break; 00156 00157 case HC_SMOOTH: 00158 _out = _in; 00159 break; 00160 } 00161 */ 00162 } 00163 00164 00165 00166 //////////////////////////////////////////////////////////////////// 00167 // Function: HermiteCurveCV::set_name 00168 // Access: Public 00169 // Description: Sets the name associated with the CV. 00170 //////////////////////////////////////////////////////////////////// 00171 void HermiteCurveCV:: 00172 set_name(const string &name) { 00173 _name = name; 00174 } 00175 00176 00177 //////////////////////////////////////////////////////////////////// 00178 // Function: HermiteCurveCV::format_egg 00179 // Access: Public 00180 // Description: Formats the CV for output to an egg file. 00181 //////////////////////////////////////////////////////////////////// 00182 void HermiteCurveCV:: 00183 format_egg(ostream &out, int indent_level, int num_dimensions, 00184 bool show_in, bool show_out, 00185 PN_stdfloat scale_in, PN_stdfloat scale_out) const { 00186 if (show_in) { 00187 indent(out, indent_level) << "<Vertex> {\n"; 00188 show_vec3(out, indent_level + 2, _p - scale_in * _in / 3.0, 00189 num_dimensions) << "\n"; 00190 indent(out, indent_level) << "}\n"; 00191 } 00192 00193 indent(out, indent_level) << "<Vertex> {\n"; 00194 show_vec3(out, indent_level + 2, _p, num_dimensions) << "\n"; 00195 00196 indent(out, indent_level+2) << "<Scalar> continuity-type { "; 00197 switch (_type) { 00198 case HC_CUT: 00199 out << "Cut"; 00200 break; 00201 00202 case HC_FREE: 00203 out << "Free"; 00204 break; 00205 00206 case HC_G1: 00207 out << "G1"; 00208 break; 00209 00210 case HC_SMOOTH: 00211 out << "Smooth"; 00212 break; 00213 }; 00214 out << " }\n"; 00215 00216 indent(out, indent_level) << "}\n"; 00217 00218 if (show_out) { 00219 indent(out, indent_level) << "<Vertex> {\n"; 00220 show_vec3(out, indent_level + 2, _p + scale_out * _out / 3.0, 00221 num_dimensions) << "\n"; 00222 indent(out, indent_level) << "}\n"; 00223 } 00224 } 00225 00226 //////////////////////////////////////////////////////////////////// 00227 // Function: HermiteCurveCV::write_datagram 00228 // Access: Public 00229 // Description: Function to write the important information in 00230 // the particular object to a Datagram 00231 //////////////////////////////////////////////////////////////////// 00232 void HermiteCurveCV:: 00233 write_datagram(BamWriter *, Datagram &me) const { 00234 _p.write_datagram(me); 00235 _in.write_datagram(me); 00236 _out.write_datagram(me); 00237 me.add_int8(_type); 00238 me.add_string(_name); 00239 } 00240 00241 //////////////////////////////////////////////////////////////////// 00242 // Function: HermiteCurveCV::fillin 00243 // Access: Public 00244 // Description: Function that reads out of the datagram (or asks 00245 // manager to read) all of the data that is needed to 00246 // re-create this object and stores it in the appropiate 00247 // place 00248 //////////////////////////////////////////////////////////////////// 00249 void HermiteCurveCV:: 00250 fillin(DatagramIterator &scan, BamReader *) { 00251 _p.read_datagram(scan); 00252 _in.read_datagram(scan); 00253 _out.read_datagram(scan); 00254 00255 _type = scan.get_int8(); 00256 _name = scan.get_string(); 00257 } 00258 00259 //////////////////////////////////////////////////////////////////// 00260 // Function: HermiteCurve::Constructor 00261 // Access: Published 00262 // Description: 00263 //////////////////////////////////////////////////////////////////// 00264 HermiteCurve:: 00265 HermiteCurve() { 00266 } 00267 00268 //////////////////////////////////////////////////////////////////// 00269 // Function: HermiteCurve::Copy Constructor 00270 // Access: Published 00271 // Description: Constructs a Hermite from the indicated (possibly 00272 // non-hermite) curve. 00273 //////////////////////////////////////////////////////////////////// 00274 HermiteCurve:: 00275 HermiteCurve(const ParametricCurve &nc) { 00276 if (!nc.convert_to_hermite(this)) { 00277 parametrics_cat->warning() 00278 << "Cannot make a Hermite from the indicated curve." 00279 << endl; 00280 } 00281 } 00282 00283 00284 //////////////////////////////////////////////////////////////////// 00285 // Function: HermiteCurve::Destructor 00286 // Access: Protected 00287 // Description: 00288 //////////////////////////////////////////////////////////////////// 00289 HermiteCurve:: 00290 ~HermiteCurve() { 00291 } 00292 00293 00294 00295 00296 00297 00298 //////////////////////////////////////////////////////////////////// 00299 // Function: HermiteCurve::get_num_cvs 00300 // Access: Published 00301 // Description: Returns the number of CV's in the curve. 00302 //////////////////////////////////////////////////////////////////// 00303 int HermiteCurve:: 00304 get_num_cvs() const { 00305 return _points.size(); 00306 } 00307 00308 00309 //////////////////////////////////////////////////////////////////// 00310 // Function: HermiteCurve::insert_cv 00311 // Access: Published 00312 // Description: Inserts a new CV at the given parametric point along 00313 // the curve. If this parametric point is already on 00314 // the curve, the CV is assigned an index between its 00315 // two neighbors and the indices of all following CV's 00316 // are incremented by 1; its in and out tangents are 00317 // chosen to keep the curve consistent. If the new 00318 // parametric point is beyond the end of the existing 00319 // curve, the curve is extended to meet it and the new 00320 // CV's position, in tangent, and out tangent are set to 00321 // zero. 00322 // 00323 // The index number of the new CV is returned. 00324 //////////////////////////////////////////////////////////////////// 00325 int HermiteCurve:: 00326 insert_cv(PN_stdfloat t) { 00327 if (!is_valid() || t >= get_max_t()) { 00328 int n = append_cv(HC_SMOOTH, 0.0f, 0.0f, 0.0f); 00329 set_cv_tstart(n, t); 00330 return n; 00331 } 00332 00333 t = min(max(t, (PN_stdfloat)0.0), get_max_t()); 00334 00335 int n = find_cv(t); 00336 nassertr(n+1<get_num_cvs(), 0); 00337 00338 HermiteCurveCV cv; 00339 LVecBase3 tan; 00340 cv._type = HC_SMOOTH; 00341 get_pt(t, cv._p, tan); 00342 cv._out = cv._in = tan * 0.5f; 00343 00344 _points.insert(_points.begin() + n + 1, cv); 00345 bool result = 00346 insert_curveseg(n, new CubicCurveseg, t - get_cv_tstart(n)); 00347 nassertr(result, 0); 00348 00349 recompute_basis(); 00350 invalidate_all(); 00351 00352 return n + 1; 00353 } 00354 00355 00356 //////////////////////////////////////////////////////////////////// 00357 // Function: HermiteCurve::append_cv 00358 // Access: Published 00359 // Description: Adds a new CV to the end of the curve. The new CV is 00360 // given initial in/out tangents of 0. The return value 00361 // is the index of the new CV. 00362 //////////////////////////////////////////////////////////////////// 00363 int HermiteCurve:: 00364 append_cv(int type, PN_stdfloat x, PN_stdfloat y, PN_stdfloat z) { 00365 HermiteCurveCV cv; 00366 cv.set_type(type); 00367 cv.set_point(LVecBase3(x, y, z)); 00368 cv.set_in(zerovec_3); 00369 cv.set_out(zerovec_3); 00370 _points.push_back(cv); 00371 if (_points.size()>1) { 00372 bool result = 00373 insert_curveseg(_segs.size(), new CubicCurveseg, 1.0f); 00374 nassertr(result, 0); 00375 } 00376 00377 recompute_basis(); 00378 invalidate_all(); 00379 00380 return _points.size()-1; 00381 } 00382 00383 00384 //////////////////////////////////////////////////////////////////// 00385 // Function: HermiteCurve::remove_cv 00386 // Access: Published 00387 // Description: Removes the given CV from the curve. Returns true if 00388 // the CV existed, false otherwise. 00389 //////////////////////////////////////////////////////////////////// 00390 bool HermiteCurve:: 00391 remove_cv(int n) { 00392 if (n < 0 || n >= (int)_points.size()) { 00393 return false; 00394 } 00395 00396 _points.erase(_points.begin() + n); 00397 if (_segs.size()>0) { 00398 remove_curveseg(_segs.size()-1); 00399 } 00400 00401 recompute_basis(); 00402 invalidate_all(); 00403 return true; 00404 } 00405 00406 00407 //////////////////////////////////////////////////////////////////// 00408 // Function: HermiteCurve::remove_all_cvs 00409 // Access: Published 00410 // Description: Removes all CV's from the curve. 00411 //////////////////////////////////////////////////////////////////// 00412 void HermiteCurve:: 00413 remove_all_cvs() { 00414 _points.erase(_points.begin(), _points.end()); 00415 remove_all_curvesegs(); 00416 00417 invalidate_all(); 00418 } 00419 00420 00421 00422 00423 //////////////////////////////////////////////////////////////////// 00424 // Function: HermiteCurve::set_cv_type 00425 // Access: Published 00426 // Description: Changes the given CV's continuity type. Legal values 00427 // are HC_CUT, HC_FREE, HC_G1, or HC_SMOOTH. 00428 // 00429 // Other than HC_CUT, these have no effect on the actual 00430 // curve; it remains up to user software to impose the 00431 // constraints these imply. 00432 // 00433 // HC_CUT implies a disconnection of the curve; HC_FREE 00434 // imposes no constraints on the tangents; HC_G1 00435 // forces the tangents to be collinear, and HC_SMOOTH 00436 // forces the tangents to be identical. Setting type 00437 // type to HC_G1 or HC_SMOOTH may adjust the out 00438 // tangent to match the in tangent. 00439 //////////////////////////////////////////////////////////////////// 00440 bool HermiteCurve:: 00441 set_cv_type(int n, int type) { 00442 if (n < 0 || n >= (int)_points.size()) { 00443 return false; 00444 } 00445 00446 bool changed_cut = false; 00447 00448 if (type!=_points[n]._type) { 00449 changed_cut = (type==HC_CUT || _points[n]._type==HC_CUT); 00450 _points[n].set_type(type); 00451 } 00452 00453 invalidate_cv(n, changed_cut); 00454 return true; 00455 } 00456 00457 00458 //////////////////////////////////////////////////////////////////// 00459 // Function: HermiteCurve::set_cv_point 00460 // Access: Published 00461 // Description: Changes the given CV's position. 00462 //////////////////////////////////////////////////////////////////// 00463 bool HermiteCurve:: 00464 set_cv_point(int n, PN_stdfloat x, PN_stdfloat y, PN_stdfloat z) { 00465 if (n < 0 || n >= (int)_points.size()) { 00466 return false; 00467 } 00468 _points[n].set_point(LVecBase3(x, y, z)); 00469 invalidate_cv(n, false); 00470 return true; 00471 } 00472 00473 //////////////////////////////////////////////////////////////////// 00474 // Function: HermiteCurve::set_cv_in 00475 // Access: Published 00476 // Description: Changes the given CV's in tangent. Depending on the 00477 // continuity type, this may also adjust the out 00478 // tangent. 00479 //////////////////////////////////////////////////////////////////// 00480 bool HermiteCurve:: 00481 set_cv_in(int n, PN_stdfloat x, PN_stdfloat y, PN_stdfloat z) { 00482 if (n < 0 || n >= (int)_points.size()) { 00483 return false; 00484 } 00485 _points[n].set_in(LVecBase3(x, y, z)); 00486 invalidate_cv(n, false); 00487 return true; 00488 } 00489 00490 //////////////////////////////////////////////////////////////////// 00491 // Function: HermiteCurve::set_cv_out 00492 // Access: Published 00493 // Description: Changes the given CV's out tangent. Depending on the 00494 // continuity type, this may also adjust the in 00495 // tangent. 00496 //////////////////////////////////////////////////////////////////// 00497 bool HermiteCurve:: 00498 set_cv_out(int n, PN_stdfloat x, PN_stdfloat y, PN_stdfloat z) { 00499 if (n < 0 || n >= (int)_points.size()) { 00500 return false; 00501 } 00502 _points[n].set_out(LVecBase3(x, y, z)); 00503 invalidate_cv(n, false); 00504 return true; 00505 } 00506 00507 //////////////////////////////////////////////////////////////////// 00508 // Function: HermiteCurve::set_cv_tstart 00509 // Access: Published 00510 // Description: Changes the given CV's parametric starting time. 00511 // This may affect the shape of the curve. 00512 //////////////////////////////////////////////////////////////////// 00513 bool HermiteCurve:: 00514 set_cv_tstart(int n, PN_stdfloat tstart) { 00515 if (n <= 0 || n >= (int)_points.size()) { 00516 return false; 00517 } 00518 if (fabs(tstart - get_cv_tstart(n)) > 0.0001f) { 00519 set_tlength(n-1, tstart - get_tstart(n-1)); 00520 recompute_basis(); 00521 invalidate_all(); 00522 } 00523 return true; 00524 } 00525 00526 00527 //////////////////////////////////////////////////////////////////// 00528 // Function: HermiteCurve::set_cv_name 00529 // Access: Published 00530 // Description: Changes the name associated with a particular CV. 00531 //////////////////////////////////////////////////////////////////// 00532 bool HermiteCurve:: 00533 set_cv_name(int n, const char *name) { 00534 if (n < 0 || n >= (int)_points.size()) { 00535 return false; 00536 } 00537 _points[n].set_name(name); 00538 return true; 00539 } 00540 00541 00542 00543 //////////////////////////////////////////////////////////////////// 00544 // Function: HermiteCurve::get_cv_type 00545 // Access: Published 00546 // Description: Returns the given CV's continuity type, HC_CUT, 00547 // HC_FREE, HC_G1, or HC_SMOOTH, or 0 if there is 00548 // no such CV. 00549 //////////////////////////////////////////////////////////////////// 00550 int HermiteCurve:: 00551 get_cv_type(int n) const { 00552 if (n < 0 || n >= (int)_points.size()) { 00553 return 0; 00554 } 00555 00556 return _points[n]._type; 00557 } 00558 00559 00560 //////////////////////////////////////////////////////////////////// 00561 // Function: HermiteCurve::get_cv_point 00562 // Access: Published 00563 // Description: Returns the position of the given CV. 00564 //////////////////////////////////////////////////////////////////// 00565 const LVecBase3 &HermiteCurve:: 00566 get_cv_point(int n) const { 00567 if (n < 0 || n >= (int)_points.size()) { 00568 return zerovec_3; 00569 } 00570 00571 return _points[n]._p; 00572 } 00573 void HermiteCurve:: 00574 get_cv_point(int n, LVecBase3 &v) const { 00575 v = get_cv_point(n); 00576 } 00577 00578 00579 //////////////////////////////////////////////////////////////////// 00580 // Function: HermiteCurve::get_cv_in 00581 // Access: Published 00582 // Description: Returns the in tangent of the given CV. 00583 //////////////////////////////////////////////////////////////////// 00584 const LVecBase3 &HermiteCurve:: 00585 get_cv_in(int n) const { 00586 if (n < 0 || n >= (int)_points.size() || _points[n-1]._type==HC_CUT) { 00587 return zerovec_3; 00588 } 00589 00590 return _points[n]._in; 00591 } 00592 void HermiteCurve:: 00593 get_cv_in(int n, LVecBase3 &v) const { 00594 v = get_cv_in(n); 00595 } 00596 00597 00598 //////////////////////////////////////////////////////////////////// 00599 // Function: HermiteCurve::get_cv_out 00600 // Access: Published 00601 // Description: Returns the out tangent of the given CV. 00602 //////////////////////////////////////////////////////////////////// 00603 const LVecBase3 &HermiteCurve:: 00604 get_cv_out(int n) const { 00605 if (n < 0 || n >= (int)_points.size() || _points[n]._type==HC_CUT) { 00606 return zerovec_3; 00607 } 00608 00609 return _points[n]._out; 00610 } 00611 void HermiteCurve:: 00612 get_cv_out(int n, LVecBase3 &v) const { 00613 v = get_cv_out(n); 00614 } 00615 00616 00617 //////////////////////////////////////////////////////////////////// 00618 // Function: HermiteCurve::get_cv_tstart 00619 // Access: Published 00620 // Description: Returns the starting point in parametric space of the 00621 // given CV. 00622 //////////////////////////////////////////////////////////////////// 00623 PN_stdfloat HermiteCurve:: 00624 get_cv_tstart(int n) const { 00625 if (n<0) { 00626 return 0.0f; 00627 } else if (n >= (int)_points.size()) { 00628 return get_max_t(); 00629 } 00630 00631 return get_tstart(n); 00632 } 00633 00634 //////////////////////////////////////////////////////////////////// 00635 // Function: HermiteCurve::get_cv_name 00636 // Access: Published 00637 // Description: Returns the name of the given CV, or NULL. 00638 //////////////////////////////////////////////////////////////////// 00639 string HermiteCurve:: 00640 get_cv_name(int n) const { 00641 if (n < 0 || n >= (int)_points.size()) { 00642 return string(); 00643 } 00644 00645 return _points[n]._name; 00646 } 00647 00648 00649 //////////////////////////////////////////////////////////////////// 00650 // Function: HermiteCurve::output 00651 // Access: Public, Virtual 00652 // Description: 00653 //////////////////////////////////////////////////////////////////// 00654 void HermiteCurve:: 00655 output(ostream &out) const { 00656 PiecewiseCurve::output(out); 00657 00658 out << " ("; 00659 switch (get_curve_type()) { 00660 case PCT_T: 00661 out << "in T, "; 00662 break; 00663 00664 case PCT_XYZ: 00665 out << "in XYZ, "; 00666 break; 00667 00668 case PCT_HPR: 00669 out << "in HPR, "; 00670 break; 00671 00672 default: 00673 break; 00674 } 00675 00676 out << get_num_cvs() << " CV's)"; 00677 } 00678 00679 //////////////////////////////////////////////////////////////////// 00680 // Function: HermiteCurve::write_cv 00681 // Access: Published 00682 // Description: 00683 //////////////////////////////////////////////////////////////////// 00684 void HermiteCurve:: 00685 write_cv(ostream &out, int n) const { 00686 out << "CV"; 00687 if (!get_cv_name(n).empty()) { 00688 out << " " << get_cv_name(n); 00689 } 00690 00691 out << " at t = " << get_cv_tstart(n) 00692 << "\npoint = " << get_cv_point(n) 00693 << "\nin = " << get_cv_in(n) << " out = " << get_cv_out(n) 00694 << "\ncontinuity type = "; 00695 00696 switch (get_cv_type(n)) { 00697 case HC_CUT: 00698 out << "Cut"; 00699 break; 00700 00701 case HC_FREE: 00702 out << "Free"; 00703 break; 00704 00705 case HC_G1: 00706 out << "G1"; 00707 break; 00708 00709 case HC_SMOOTH: 00710 out << "Smooth"; 00711 break; 00712 00713 default: 00714 break; 00715 } 00716 00717 out << "\n"; 00718 } 00719 00720 00721 //////////////////////////////////////////////////////////////////// 00722 // Function: HermiteCurve::rebuild_curveseg 00723 // Access: Public, Virtual 00724 // Description: Rebuilds the current curve segment (as selected by 00725 // the most recent call to find_curve()) according to 00726 // the specified properties (see 00727 // CubicCurveseg::compute_seg). Returns true if 00728 // possible, false if something goes horribly wrong. 00729 //////////////////////////////////////////////////////////////////// 00730 bool HermiteCurve:: 00731 rebuild_curveseg(int, PN_stdfloat, const LVecBase4 &, 00732 int, PN_stdfloat, const LVecBase4 &, 00733 int, PN_stdfloat, const LVecBase4 &, 00734 int, PN_stdfloat, const LVecBase4 &) { 00735 cerr << "rebuild_curveseg not implemented for this curve type.\n"; 00736 return false; 00737 } 00738 00739 //////////////////////////////////////////////////////////////////// 00740 // Function: HermiteCurve::format_egg 00741 // Access: Public 00742 // Description: Formats the Hermite curve for output to an Egg file. 00743 //////////////////////////////////////////////////////////////////// 00744 bool HermiteCurve:: 00745 format_egg(ostream &out, const string &name, const string &curve_type, 00746 int indent_level) const { 00747 indent(out, indent_level) 00748 << "<VertexPool> " << name << ".pool {\n"; 00749 00750 int i; 00751 for (i = 0; i < (int)_points.size(); i++) { 00752 bool show_in = (i != 0); 00753 bool show_out = (i != (int)_points.size()-1); 00754 _points[i].format_egg(out, indent_level + 2, _num_dimensions, 00755 show_in, show_out, 00756 show_in ? get_tlength(i-1) : 0.0f, 00757 show_out ? get_tlength(i) : 0.0f); 00758 } 00759 indent(out, indent_level) << "}\n"; 00760 00761 indent(out, indent_level) << "<BezierCurve> " << name << " {\n"; 00762 00763 if (!curve_type.empty()) { 00764 indent(out, indent_level+2) 00765 << "<Scalar> type { " << curve_type << " }\n"; 00766 } 00767 00768 indent(out, indent_level+2) << "<TLengths> {"; 00769 if (_points.size() > 1) { 00770 for (i = 0; i < (int)_segs.size(); i++) { 00771 if (i%10 == 1) { 00772 out << "\n"; 00773 indent(out, indent_level+3); 00774 } 00775 out << " " << get_tlength(i); 00776 } 00777 } 00778 out << "\n"; 00779 indent(out, indent_level+2) << "}\n"; 00780 00781 indent(out, indent_level+2) << "<VertexRef> {"; 00782 for (i = 1; i <= (int)_points.size() * 3 - 2; i++) { 00783 if (i%10 == 1) { 00784 out << "\n"; 00785 indent(out, indent_level+3); 00786 } 00787 out << " " << i; 00788 } 00789 out << "\n"; 00790 indent(out, indent_level+4) << "<Ref> { " << name << ".pool }\n"; 00791 indent(out, indent_level+2) << "}\n"; 00792 00793 indent(out, indent_level) << "}\n"; 00794 00795 return true; 00796 } 00797 00798 00799 static void 00800 wrap_hpr(const LVecBase3 &hpr1, LVecBase3 &hpr2) { 00801 for (int i = 0; i < 3; i++) { 00802 while ((hpr2[i] - hpr1[i]) > 180.0) { 00803 hpr2[i] -= 360.0; 00804 } 00805 00806 while ((hpr2[i] - hpr1[i]) < -180.0) { 00807 hpr2[i] += 360.0; 00808 } 00809 } 00810 } 00811 00812 //////////////////////////////////////////////////////////////////// 00813 // Function: HermiteCurve::invalidate_cv 00814 // Access: Protected 00815 // Description: Recomputes the CV and its neighbors appropriately 00816 // after a change. 00817 //////////////////////////////////////////////////////////////////// 00818 void HermiteCurve:: 00819 invalidate_cv(int n, bool redo_all) { 00820 PN_stdfloat t1 = 0.0f, t2 = get_max_t(); 00821 if (n>0 && _points[n-1]._type!=HC_CUT) { 00822 const HermiteCurveCV &p1 = _points[n-1]; 00823 HermiteCurveCV p2(_points[n]); 00824 if (_curve_type == PCT_HPR) { 00825 wrap_hpr(p1._p, p2._p); 00826 } 00827 get_curveseg(n-1)->hermite_basis(p1, p2, get_tlength(n-1)); 00828 t1 = get_cv_tstart(n-1); 00829 } 00830 00831 if (n+1 < (int)_points.size()) { 00832 if (_points[n]._type==HC_CUT) { 00833 BezierSeg seg; 00834 seg._v[0] = seg._v[1] = seg._v[2] = seg._v[3] = _points[n]._p; 00835 get_curveseg(n)->bezier_basis(seg); 00836 } else { 00837 const HermiteCurveCV &p1 = _points[n]; 00838 HermiteCurveCV p2(_points[n+1]); 00839 if (_curve_type == PCT_HPR) { 00840 wrap_hpr(p1._p, p2._p); 00841 } 00842 get_curveseg(n)->hermite_basis(p1, p2, get_tlength(n)); 00843 t2 = get_cv_tstart(n+2); 00844 } 00845 } 00846 00847 if (is_valid()) { 00848 if (redo_all) { 00849 invalidate_all(); 00850 } else { 00851 invalidate(t1, t2); 00852 } 00853 } 00854 } 00855 00856 00857 00858 //////////////////////////////////////////////////////////////////// 00859 // Function: HermiteCurve::find_cv 00860 // Access: Protected 00861 // Description: Finds the CV immediately preceding the given value of 00862 // t. 00863 //////////////////////////////////////////////////////////////////// 00864 int HermiteCurve:: 00865 find_cv(PN_stdfloat t) { 00866 nassertr(is_valid(), 0); 00867 00868 int n; 00869 for (n = 0; n < (int)_segs.size(); n++) { 00870 if (_segs[n]._tend+0.00001 > t) { 00871 break; 00872 } 00873 } 00874 00875 return n; 00876 } 00877 00878 00879 //////////////////////////////////////////////////////////////////// 00880 // Function: HermiteCurve::recompute_basis 00881 // Access: Protected 00882 // Description: Recomputes the coefficients for all the CV's in the 00883 // curve. This is intended to be called whenever the 00884 // CV's have been changed in some drastic way, and it's 00885 // safest just to recompute everything. 00886 //////////////////////////////////////////////////////////////////// 00887 void HermiteCurve:: 00888 recompute_basis() { 00889 int n; 00890 for (n = 0; n < (int)_segs.size(); n++) { 00891 if (_points[n]._type==HC_CUT) { 00892 BezierSeg seg; 00893 seg._v[0] = seg._v[1] = seg._v[2] = seg._v[3] = _points[n]._p; 00894 get_curveseg(n)->bezier_basis(seg); 00895 } else { 00896 const HermiteCurveCV &p1 = _points[n]; 00897 HermiteCurveCV p2(_points[n+1]); 00898 if (_curve_type == PCT_HPR) { 00899 wrap_hpr(p1._p, p2._p); 00900 } 00901 get_curveseg(n)->hermite_basis(p1, p2, get_tlength(n)); 00902 } 00903 } 00904 } 00905 00906 00907 //////////////////////////////////////////////////////////////////// 00908 // Function: HermiteCurve::register_with_factory 00909 // Access: Public, Static 00910 // Description: Initializes the factory for reading these things from 00911 // Bam files. 00912 //////////////////////////////////////////////////////////////////// 00913 void HermiteCurve:: 00914 register_with_read_factory() { 00915 BamReader::get_factory()->register_factory(get_class_type(), make_HermiteCurve); 00916 } 00917 00918 //////////////////////////////////////////////////////////////////// 00919 // Function: HermiteCurve::make_HermiteCurve 00920 // Access: Protected 00921 // Description: Factory method to generate an object of this type. 00922 //////////////////////////////////////////////////////////////////// 00923 TypedWritable *HermiteCurve:: 00924 make_HermiteCurve(const FactoryParams ¶ms) { 00925 HermiteCurve *me = new HermiteCurve; 00926 DatagramIterator scan; 00927 BamReader *manager; 00928 00929 parse_params(params, scan, manager); 00930 me->fillin(scan, manager); 00931 return me; 00932 } 00933 00934 //////////////////////////////////////////////////////////////////// 00935 // Function: HermiteCurve::write_datagram 00936 // Access: Protected, Virtual 00937 // Description: Function to write the important information in 00938 // the particular object to a Datagram 00939 //////////////////////////////////////////////////////////////////// 00940 void HermiteCurve:: 00941 write_datagram(BamWriter *manager, Datagram &me) { 00942 PiecewiseCurve::write_datagram(manager, me); 00943 00944 me.add_uint32(_points.size()); 00945 size_t i; 00946 for (i = 0; i < _points.size(); i++) { 00947 _points[i].write_datagram(manager, me); 00948 } 00949 } 00950 00951 //////////////////////////////////////////////////////////////////// 00952 // Function: HermiteCurve::fillin 00953 // Access: Protected 00954 // Description: Function that reads out of the datagram (or asks 00955 // manager to read) all of the data that is needed to 00956 // re-create this object and stores it in the appropiate 00957 // place 00958 //////////////////////////////////////////////////////////////////// 00959 void HermiteCurve:: 00960 fillin(DatagramIterator &scan, BamReader *manager) { 00961 PiecewiseCurve::fillin(scan, manager); 00962 00963 size_t num_points = scan.get_uint32(); 00964 _points.reserve(num_points); 00965 size_t i; 00966 for (i = 0; i < num_points; i++) { 00967 HermiteCurveCV cv; 00968 cv.fillin(scan, manager); 00969 _points.push_back(cv); 00970 } 00971 }