Panda3D
hermiteCurve.cxx
1 // Filename: hermiteCurve.cxx
2 // Created by: drose (27Feb98)
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 "pandabase.h"
16 #include "hermiteCurve.h"
17 #include "config_parametrics.h"
18 #include "luse.h"
19 
20 #include "indent.h"
21 #include "datagram.h"
22 #include "datagramIterator.h"
23 #include "bamWriter.h"
24 #include "bamReader.h"
25 
26 #include <math.h>
27 
28 TypeHandle HermiteCurve::_type_handle;
29 
30 static const LVecBase3 zerovec_3 = LVecBase3(0.0f, 0.0f, 0.0f);
31 // This is returned occasionally from some of the functions, and is
32 // used from time to time as an initializer.
33 
34 
35 ////////////////////////////////////////////////////////////////////
36 // Function: show_vec3
37 // Description: This function writes a LVecBase3, with a specified
38 // number of significant dimensions.
39 ////////////////////////////////////////////////////////////////////
40 static ostream &
41 show_vec3(ostream &out, int indent_level, const LVecBase3 &v,
42  int num_dimensions) {
43  indent(out, indent_level) << v[0];
44  for (int i = 1; i<num_dimensions; i++) {
45  out << " " << v[i];
46  }
47  return out;
48 }
49 
50 ////////////////////////////////////////////////////////////////////
51 // Function: HermiteCurveCV::constructor
52 // Access: Public
53 // Description:
54 ////////////////////////////////////////////////////////////////////
55 HermiteCurveCV::
56 HermiteCurveCV() {
57 }
58 
59 
60 ////////////////////////////////////////////////////////////////////
61 // Function: HermiteCurveCV::copy_constructor
62 // Access: Public
63 // Description:
64 ////////////////////////////////////////////////////////////////////
65 HermiteCurveCV::
66 HermiteCurveCV(const HermiteCurveCV &c) :
67  _p(c._p), _in(c._in), _out(c._out),
68  _type(c._type), _name(c._name)
69 {
70 }
71 
72 
73 ////////////////////////////////////////////////////////////////////
74 // Function: HermiteCurveCV::destructor
75 // Access: Public
76 // Description:
77 ////////////////////////////////////////////////////////////////////
78 HermiteCurveCV::
79 ~HermiteCurveCV() {
80 }
81 
82 
83 
84 ////////////////////////////////////////////////////////////////////
85 // Function: HermiteCurveCV::set_in
86 // Access: Public
87 // Description: Sets the CV's in tangent.
88 ////////////////////////////////////////////////////////////////////
90 set_in(const LVecBase3 &in) {
91  _in = in;
92  /*
93  PN_stdfloat l;
94  switch (_type) {
95  case HC_G1:
96  l = _in.length();
97  if (l!=0.0f) {
98  _out = _in * _out.length() / l;
99  }
100  break;
101 
102  case HC_SMOOTH:
103  _out = _in;
104  break;
105  }
106  */
107 }
108 
109 
110 ////////////////////////////////////////////////////////////////////
111 // Function: HermiteCurveCV::set_out
112 // Access: Public
113 // Description: Sets the CV's out tangent.
114 ////////////////////////////////////////////////////////////////////
115 void HermiteCurveCV::
116 set_out(const LVecBase3 &out) {
117  _out = out;
118  /*
119  PN_stdfloat l;
120  switch (_type) {
121  case HC_G1:
122  l = _out.length();
123  if (l!=0.0f) {
124  _in = _out * _in.length() / l;
125  }
126  break;
127 
128  case HC_SMOOTH:
129  _in = _out;
130  break;
131  }
132  */
133 }
134 
135 
136 ////////////////////////////////////////////////////////////////////
137 // Function: HermiteCurveCV::set_type
138 // Access: Public
139 // Description: Sets the continuity type of the CV. Values may be
140 // HC_CUT, indicating a discontinous break in the curve,
141 // HC_FREE, for unconstrained in and out tangents,
142 // HC_G1, for in and out tangents constrained to be
143 // collinear, and HC_SMOOTH, for in and out tangents
144 // constrained to be equal. Other than HC_CUT, these
145 // are for documentation only; setting this has no
146 // direct effect on the tangents.
147 ////////////////////////////////////////////////////////////////////
148 void HermiteCurveCV::
149 set_type(int type) {
150  _type = type;
151  /*
152  switch (_type) {
153  case HC_G1:
154  _out = _out.length() * _in;
155  break;
156 
157  case HC_SMOOTH:
158  _out = _in;
159  break;
160  }
161  */
162 }
163 
164 
165 
166 ////////////////////////////////////////////////////////////////////
167 // Function: HermiteCurveCV::set_name
168 // Access: Public
169 // Description: Sets the name associated with the CV.
170 ////////////////////////////////////////////////////////////////////
171 void HermiteCurveCV::
172 set_name(const string &name) {
173  _name = name;
174 }
175 
176 
177 ////////////////////////////////////////////////////////////////////
178 // Function: HermiteCurveCV::format_egg
179 // Access: Public
180 // Description: Formats the CV for output to an egg file.
181 ////////////////////////////////////////////////////////////////////
182 void HermiteCurveCV::
183 format_egg(ostream &out, int indent_level, int num_dimensions,
184  bool show_in, bool show_out,
185  PN_stdfloat scale_in, PN_stdfloat scale_out) const {
186  if (show_in) {
187  indent(out, indent_level) << "<Vertex> {\n";
188  show_vec3(out, indent_level + 2, _p - scale_in * _in / 3.0,
189  num_dimensions) << "\n";
190  indent(out, indent_level) << "}\n";
191  }
192 
193  indent(out, indent_level) << "<Vertex> {\n";
194  show_vec3(out, indent_level + 2, _p, num_dimensions) << "\n";
195 
196  indent(out, indent_level+2) << "<Scalar> continuity-type { ";
197  switch (_type) {
198  case HC_CUT:
199  out << "Cut";
200  break;
201 
202  case HC_FREE:
203  out << "Free";
204  break;
205 
206  case HC_G1:
207  out << "G1";
208  break;
209 
210  case HC_SMOOTH:
211  out << "Smooth";
212  break;
213  };
214  out << " }\n";
215 
216  indent(out, indent_level) << "}\n";
217 
218  if (show_out) {
219  indent(out, indent_level) << "<Vertex> {\n";
220  show_vec3(out, indent_level + 2, _p + scale_out * _out / 3.0,
221  num_dimensions) << "\n";
222  indent(out, indent_level) << "}\n";
223  }
224 }
225 
226 ////////////////////////////////////////////////////////////////////
227 // Function: HermiteCurveCV::write_datagram
228 // Access: Public
229 // Description: Function to write the important information in
230 // the particular object to a Datagram
231 ////////////////////////////////////////////////////////////////////
232 void HermiteCurveCV::
234  _p.write_datagram(me);
235  _in.write_datagram(me);
236  _out.write_datagram(me);
237  me.add_int8(_type);
238  me.add_string(_name);
239 }
240 
241 ////////////////////////////////////////////////////////////////////
242 // Function: HermiteCurveCV::fillin
243 // Access: Public
244 // Description: Function that reads out of the datagram (or asks
245 // manager to read) all of the data that is needed to
246 // re-create this object and stores it in the appropiate
247 // place
248 ////////////////////////////////////////////////////////////////////
249 void HermiteCurveCV::
251  _p.read_datagram(scan);
252  _in.read_datagram(scan);
253  _out.read_datagram(scan);
254 
255  _type = scan.get_int8();
256  _name = scan.get_string();
257 }
258 
259 ////////////////////////////////////////////////////////////////////
260 // Function: HermiteCurve::Constructor
261 // Access: Published
262 // Description:
263 ////////////////////////////////////////////////////////////////////
264 HermiteCurve::
265 HermiteCurve() {
266 }
267 
268 ////////////////////////////////////////////////////////////////////
269 // Function: HermiteCurve::Copy Constructor
270 // Access: Published
271 // Description: Constructs a Hermite from the indicated (possibly
272 // non-hermite) curve.
273 ////////////////////////////////////////////////////////////////////
274 HermiteCurve::
275 HermiteCurve(const ParametricCurve &nc) {
276  if (!nc.convert_to_hermite(this)) {
277  parametrics_cat->warning()
278  << "Cannot make a Hermite from the indicated curve."
279  << endl;
280  }
281 }
282 
283 
284 ////////////////////////////////////////////////////////////////////
285 // Function: HermiteCurve::Destructor
286 // Access: Protected
287 // Description:
288 ////////////////////////////////////////////////////////////////////
289 HermiteCurve::
290 ~HermiteCurve() {
291 }
292 
293 
294 
295 
296 
297 
298 ////////////////////////////////////////////////////////////////////
299 // Function: HermiteCurve::get_num_cvs
300 // Access: Published
301 // Description: Returns the number of CV's in the curve.
302 ////////////////////////////////////////////////////////////////////
303 int HermiteCurve::
304 get_num_cvs() const {
305  return _points.size();
306 }
307 
308 
309 ////////////////////////////////////////////////////////////////////
310 // Function: HermiteCurve::insert_cv
311 // Access: Published
312 // Description: Inserts a new CV at the given parametric point along
313 // the curve. If this parametric point is already on
314 // the curve, the CV is assigned an index between its
315 // two neighbors and the indices of all following CV's
316 // are incremented by 1; its in and out tangents are
317 // chosen to keep the curve consistent. If the new
318 // parametric point is beyond the end of the existing
319 // curve, the curve is extended to meet it and the new
320 // CV's position, in tangent, and out tangent are set to
321 // zero.
322 //
323 // The index number of the new CV is returned.
324 ////////////////////////////////////////////////////////////////////
325 int HermiteCurve::
326 insert_cv(PN_stdfloat t) {
327  if (!is_valid() || t >= get_max_t()) {
328  int n = append_cv(HC_SMOOTH, 0.0f, 0.0f, 0.0f);
329  set_cv_tstart(n, t);
330  return n;
331  }
332 
333  t = min(max(t, (PN_stdfloat)0.0), get_max_t());
334 
335  int n = find_cv(t);
336  nassertr(n+1<get_num_cvs(), 0);
337 
338  HermiteCurveCV cv;
339  LVecBase3 tan;
340  cv._type = HC_SMOOTH;
341  get_pt(t, cv._p, tan);
342  cv._out = cv._in = tan * 0.5f;
343 
344  _points.insert(_points.begin() + n + 1, cv);
345  bool result =
347  nassertr(result, 0);
348 
349  recompute_basis();
350  invalidate_all();
351 
352  return n + 1;
353 }
354 
355 
356 ////////////////////////////////////////////////////////////////////
357 // Function: HermiteCurve::append_cv
358 // Access: Published
359 // Description: Adds a new CV to the end of the curve. The new CV is
360 // given initial in/out tangents of 0. The return value
361 // is the index of the new CV.
362 ////////////////////////////////////////////////////////////////////
363 int HermiteCurve::
364 append_cv(int type, PN_stdfloat x, PN_stdfloat y, PN_stdfloat z) {
365  HermiteCurveCV cv;
366  cv.set_type(type);
367  cv.set_point(LVecBase3(x, y, z));
368  cv.set_in(zerovec_3);
369  cv.set_out(zerovec_3);
370  _points.push_back(cv);
371  if (_points.size()>1) {
372  bool result =
373  insert_curveseg(_segs.size(), new CubicCurveseg, 1.0f);
374  nassertr(result, 0);
375  }
376 
377  recompute_basis();
378  invalidate_all();
379 
380  return _points.size()-1;
381 }
382 
383 
384 ////////////////////////////////////////////////////////////////////
385 // Function: HermiteCurve::remove_cv
386 // Access: Published
387 // Description: Removes the given CV from the curve. Returns true if
388 // the CV existed, false otherwise.
389 ////////////////////////////////////////////////////////////////////
390 bool HermiteCurve::
391 remove_cv(int n) {
392  if (n < 0 || n >= (int)_points.size()) {
393  return false;
394  }
395 
396  _points.erase(_points.begin() + n);
397  if (_segs.size()>0) {
398  remove_curveseg(_segs.size()-1);
399  }
400 
401  recompute_basis();
402  invalidate_all();
403  return true;
404 }
405 
406 
407 ////////////////////////////////////////////////////////////////////
408 // Function: HermiteCurve::remove_all_cvs
409 // Access: Published
410 // Description: Removes all CV's from the curve.
411 ////////////////////////////////////////////////////////////////////
412 void HermiteCurve::
414  _points.erase(_points.begin(), _points.end());
416 
417  invalidate_all();
418 }
419 
420 
421 
422 
423 ////////////////////////////////////////////////////////////////////
424 // Function: HermiteCurve::set_cv_type
425 // Access: Published
426 // Description: Changes the given CV's continuity type. Legal values
427 // are HC_CUT, HC_FREE, HC_G1, or HC_SMOOTH.
428 //
429 // Other than HC_CUT, these have no effect on the actual
430 // curve; it remains up to user software to impose the
431 // constraints these imply.
432 //
433 // HC_CUT implies a disconnection of the curve; HC_FREE
434 // imposes no constraints on the tangents; HC_G1
435 // forces the tangents to be collinear, and HC_SMOOTH
436 // forces the tangents to be identical. Setting type
437 // type to HC_G1 or HC_SMOOTH may adjust the out
438 // tangent to match the in tangent.
439 ////////////////////////////////////////////////////////////////////
440 bool HermiteCurve::
441 set_cv_type(int n, int type) {
442  if (n < 0 || n >= (int)_points.size()) {
443  return false;
444  }
445 
446  bool changed_cut = false;
447 
448  if (type!=_points[n]._type) {
449  changed_cut = (type==HC_CUT || _points[n]._type==HC_CUT);
450  _points[n].set_type(type);
451  }
452 
453  invalidate_cv(n, changed_cut);
454  return true;
455 }
456 
457 
458 ////////////////////////////////////////////////////////////////////
459 // Function: HermiteCurve::set_cv_point
460 // Access: Published
461 // Description: Changes the given CV's position.
462 ////////////////////////////////////////////////////////////////////
463 bool HermiteCurve::
464 set_cv_point(int n, PN_stdfloat x, PN_stdfloat y, PN_stdfloat z) {
465  if (n < 0 || n >= (int)_points.size()) {
466  return false;
467  }
468  _points[n].set_point(LVecBase3(x, y, z));
469  invalidate_cv(n, false);
470  return true;
471 }
472 
473 ////////////////////////////////////////////////////////////////////
474 // Function: HermiteCurve::set_cv_in
475 // Access: Published
476 // Description: Changes the given CV's in tangent. Depending on the
477 // continuity type, this may also adjust the out
478 // tangent.
479 ////////////////////////////////////////////////////////////////////
480 bool HermiteCurve::
481 set_cv_in(int n, PN_stdfloat x, PN_stdfloat y, PN_stdfloat z) {
482  if (n < 0 || n >= (int)_points.size()) {
483  return false;
484  }
485  _points[n].set_in(LVecBase3(x, y, z));
486  invalidate_cv(n, false);
487  return true;
488 }
489 
490 ////////////////////////////////////////////////////////////////////
491 // Function: HermiteCurve::set_cv_out
492 // Access: Published
493 // Description: Changes the given CV's out tangent. Depending on the
494 // continuity type, this may also adjust the in
495 // tangent.
496 ////////////////////////////////////////////////////////////////////
497 bool HermiteCurve::
498 set_cv_out(int n, PN_stdfloat x, PN_stdfloat y, PN_stdfloat z) {
499  if (n < 0 || n >= (int)_points.size()) {
500  return false;
501  }
502  _points[n].set_out(LVecBase3(x, y, z));
503  invalidate_cv(n, false);
504  return true;
505 }
506 
507 ////////////////////////////////////////////////////////////////////
508 // Function: HermiteCurve::set_cv_tstart
509 // Access: Published
510 // Description: Changes the given CV's parametric starting time.
511 // This may affect the shape of the curve.
512 ////////////////////////////////////////////////////////////////////
513 bool HermiteCurve::
514 set_cv_tstart(int n, PN_stdfloat tstart) {
515  if (n <= 0 || n >= (int)_points.size()) {
516  return false;
517  }
518  if (fabs(tstart - get_cv_tstart(n)) > 0.0001f) {
519  set_tlength(n-1, tstart - get_tstart(n-1));
520  recompute_basis();
521  invalidate_all();
522  }
523  return true;
524 }
525 
526 
527 ////////////////////////////////////////////////////////////////////
528 // Function: HermiteCurve::set_cv_name
529 // Access: Published
530 // Description: Changes the name associated with a particular CV.
531 ////////////////////////////////////////////////////////////////////
532 bool HermiteCurve::
533 set_cv_name(int n, const char *name) {
534  if (n < 0 || n >= (int)_points.size()) {
535  return false;
536  }
537  _points[n].set_name(name);
538  return true;
539 }
540 
541 
542 
543 ////////////////////////////////////////////////////////////////////
544 // Function: HermiteCurve::get_cv_type
545 // Access: Published
546 // Description: Returns the given CV's continuity type, HC_CUT,
547 // HC_FREE, HC_G1, or HC_SMOOTH, or 0 if there is
548 // no such CV.
549 ////////////////////////////////////////////////////////////////////
550 int HermiteCurve::
551 get_cv_type(int n) const {
552  if (n < 0 || n >= (int)_points.size()) {
553  return 0;
554  }
555 
556  return _points[n]._type;
557 }
558 
559 
560 ////////////////////////////////////////////////////////////////////
561 // Function: HermiteCurve::get_cv_point
562 // Access: Published
563 // Description: Returns the position of the given CV.
564 ////////////////////////////////////////////////////////////////////
566 get_cv_point(int n) const {
567  if (n < 0 || n >= (int)_points.size()) {
568  return zerovec_3;
569  }
570 
571  return _points[n]._p;
572 }
573 void HermiteCurve::
574 get_cv_point(int n, LVecBase3 &v) const {
575  v = get_cv_point(n);
576 }
577 
578 
579 ////////////////////////////////////////////////////////////////////
580 // Function: HermiteCurve::get_cv_in
581 // Access: Published
582 // Description: Returns the in tangent of the given CV.
583 ////////////////////////////////////////////////////////////////////
585 get_cv_in(int n) const {
586  if (n < 0 || n >= (int)_points.size() || _points[n-1]._type==HC_CUT) {
587  return zerovec_3;
588  }
589 
590  return _points[n]._in;
591 }
592 void HermiteCurve::
593 get_cv_in(int n, LVecBase3 &v) const {
594  v = get_cv_in(n);
595 }
596 
597 
598 ////////////////////////////////////////////////////////////////////
599 // Function: HermiteCurve::get_cv_out
600 // Access: Published
601 // Description: Returns the out tangent of the given CV.
602 ////////////////////////////////////////////////////////////////////
604 get_cv_out(int n) const {
605  if (n < 0 || n >= (int)_points.size() || _points[n]._type==HC_CUT) {
606  return zerovec_3;
607  }
608 
609  return _points[n]._out;
610 }
611 void HermiteCurve::
612 get_cv_out(int n, LVecBase3 &v) const {
613  v = get_cv_out(n);
614 }
615 
616 
617 ////////////////////////////////////////////////////////////////////
618 // Function: HermiteCurve::get_cv_tstart
619 // Access: Published
620 // Description: Returns the starting point in parametric space of the
621 // given CV.
622 ////////////////////////////////////////////////////////////////////
623 PN_stdfloat HermiteCurve::
624 get_cv_tstart(int n) const {
625  if (n<0) {
626  return 0.0f;
627  } else if (n >= (int)_points.size()) {
628  return get_max_t();
629  }
630 
631  return get_tstart(n);
632 }
633 
634 ////////////////////////////////////////////////////////////////////
635 // Function: HermiteCurve::get_cv_name
636 // Access: Published
637 // Description: Returns the name of the given CV, or NULL.
638 ////////////////////////////////////////////////////////////////////
639 string HermiteCurve::
640 get_cv_name(int n) const {
641  if (n < 0 || n >= (int)_points.size()) {
642  return string();
643  }
644 
645  return _points[n]._name;
646 }
647 
648 
649 ////////////////////////////////////////////////////////////////////
650 // Function: HermiteCurve::output
651 // Access: Public, Virtual
652 // Description:
653 ////////////////////////////////////////////////////////////////////
654 void HermiteCurve::
655 output(ostream &out) const {
656  PiecewiseCurve::output(out);
657 
658  out << " (";
659  switch (get_curve_type()) {
660  case PCT_T:
661  out << "in T, ";
662  break;
663 
664  case PCT_XYZ:
665  out << "in XYZ, ";
666  break;
667 
668  case PCT_HPR:
669  out << "in HPR, ";
670  break;
671 
672  default:
673  break;
674  }
675 
676  out << get_num_cvs() << " CV's)";
677 }
678 
679 ////////////////////////////////////////////////////////////////////
680 // Function: HermiteCurve::write_cv
681 // Access: Published
682 // Description:
683 ////////////////////////////////////////////////////////////////////
684 void HermiteCurve::
685 write_cv(ostream &out, int n) const {
686  out << "CV";
687  if (!get_cv_name(n).empty()) {
688  out << " " << get_cv_name(n);
689  }
690 
691  out << " at t = " << get_cv_tstart(n)
692  << "\npoint = " << get_cv_point(n)
693  << "\nin = " << get_cv_in(n) << " out = " << get_cv_out(n)
694  << "\ncontinuity type = ";
695 
696  switch (get_cv_type(n)) {
697  case HC_CUT:
698  out << "Cut";
699  break;
700 
701  case HC_FREE:
702  out << "Free";
703  break;
704 
705  case HC_G1:
706  out << "G1";
707  break;
708 
709  case HC_SMOOTH:
710  out << "Smooth";
711  break;
712 
713  default:
714  break;
715  }
716 
717  out << "\n";
718 }
719 
720 
721 ////////////////////////////////////////////////////////////////////
722 // Function: HermiteCurve::rebuild_curveseg
723 // Access: Public, Virtual
724 // Description: Rebuilds the current curve segment (as selected by
725 // the most recent call to find_curve()) according to
726 // the specified properties (see
727 // CubicCurveseg::compute_seg). Returns true if
728 // possible, false if something goes horribly wrong.
729 ////////////////////////////////////////////////////////////////////
730 bool HermiteCurve::
731 rebuild_curveseg(int, PN_stdfloat, const LVecBase4 &,
732  int, PN_stdfloat, const LVecBase4 &,
733  int, PN_stdfloat, const LVecBase4 &,
734  int, PN_stdfloat, const LVecBase4 &) {
735  cerr << "rebuild_curveseg not implemented for this curve type.\n";
736  return false;
737 }
738 
739 ////////////////////////////////////////////////////////////////////
740 // Function: HermiteCurve::format_egg
741 // Access: Public
742 // Description: Formats the Hermite curve for output to an Egg file.
743 ////////////////////////////////////////////////////////////////////
744 bool HermiteCurve::
745 format_egg(ostream &out, const string &name, const string &curve_type,
746  int indent_level) const {
747  indent(out, indent_level)
748  << "<VertexPool> " << name << ".pool {\n";
749 
750  int i;
751  for (i = 0; i < (int)_points.size(); i++) {
752  bool show_in = (i != 0);
753  bool show_out = (i != (int)_points.size()-1);
754  _points[i].format_egg(out, indent_level + 2, _num_dimensions,
755  show_in, show_out,
756  show_in ? get_tlength(i-1) : 0.0f,
757  show_out ? get_tlength(i) : 0.0f);
758  }
759  indent(out, indent_level) << "}\n";
760 
761  indent(out, indent_level) << "<BezierCurve> " << name << " {\n";
762 
763  if (!curve_type.empty()) {
764  indent(out, indent_level+2)
765  << "<Scalar> type { " << curve_type << " }\n";
766  }
767 
768  indent(out, indent_level+2) << "<TLengths> {";
769  if (_points.size() > 1) {
770  for (i = 0; i < (int)_segs.size(); i++) {
771  if (i%10 == 1) {
772  out << "\n";
773  indent(out, indent_level+3);
774  }
775  out << " " << get_tlength(i);
776  }
777  }
778  out << "\n";
779  indent(out, indent_level+2) << "}\n";
780 
781  indent(out, indent_level+2) << "<VertexRef> {";
782  for (i = 1; i <= (int)_points.size() * 3 - 2; i++) {
783  if (i%10 == 1) {
784  out << "\n";
785  indent(out, indent_level+3);
786  }
787  out << " " << i;
788  }
789  out << "\n";
790  indent(out, indent_level+4) << "<Ref> { " << name << ".pool }\n";
791  indent(out, indent_level+2) << "}\n";
792 
793  indent(out, indent_level) << "}\n";
794 
795  return true;
796 }
797 
798 
799 static void
800 wrap_hpr(const LVecBase3 &hpr1, LVecBase3 &hpr2) {
801  for (int i = 0; i < 3; i++) {
802  while ((hpr2[i] - hpr1[i]) > 180.0) {
803  hpr2[i] -= 360.0;
804  }
805 
806  while ((hpr2[i] - hpr1[i]) < -180.0) {
807  hpr2[i] += 360.0;
808  }
809  }
810 }
811 
812 ////////////////////////////////////////////////////////////////////
813 // Function: HermiteCurve::invalidate_cv
814 // Access: Protected
815 // Description: Recomputes the CV and its neighbors appropriately
816 // after a change.
817 ////////////////////////////////////////////////////////////////////
818 void HermiteCurve::
819 invalidate_cv(int n, bool redo_all) {
820  PN_stdfloat t1 = 0.0f, t2 = get_max_t();
821  if (n>0 && _points[n-1]._type!=HC_CUT) {
822  const HermiteCurveCV &p1 = _points[n-1];
823  HermiteCurveCV p2(_points[n]);
824  if (_curve_type == PCT_HPR) {
825  wrap_hpr(p1._p, p2._p);
826  }
827  get_curveseg(n-1)->hermite_basis(p1, p2, get_tlength(n-1));
828  t1 = get_cv_tstart(n-1);
829  }
830 
831  if (n+1 < (int)_points.size()) {
832  if (_points[n]._type==HC_CUT) {
833  BezierSeg seg;
834  seg._v[0] = seg._v[1] = seg._v[2] = seg._v[3] = _points[n]._p;
835  get_curveseg(n)->bezier_basis(seg);
836  } else {
837  const HermiteCurveCV &p1 = _points[n];
838  HermiteCurveCV p2(_points[n+1]);
839  if (_curve_type == PCT_HPR) {
840  wrap_hpr(p1._p, p2._p);
841  }
842  get_curveseg(n)->hermite_basis(p1, p2, get_tlength(n));
843  t2 = get_cv_tstart(n+2);
844  }
845  }
846 
847  if (is_valid()) {
848  if (redo_all) {
849  invalidate_all();
850  } else {
851  invalidate(t1, t2);
852  }
853  }
854 }
855 
856 
857 
858 ////////////////////////////////////////////////////////////////////
859 // Function: HermiteCurve::find_cv
860 // Access: Protected
861 // Description: Finds the CV immediately preceding the given value of
862 // t.
863 ////////////////////////////////////////////////////////////////////
864 int HermiteCurve::
865 find_cv(PN_stdfloat t) {
866  nassertr(is_valid(), 0);
867 
868  int n;
869  for (n = 0; n < (int)_segs.size(); n++) {
870  if (_segs[n]._tend+0.00001 > t) {
871  break;
872  }
873  }
874 
875  return n;
876 }
877 
878 
879 ////////////////////////////////////////////////////////////////////
880 // Function: HermiteCurve::recompute_basis
881 // Access: Protected
882 // Description: Recomputes the coefficients for all the CV's in the
883 // curve. This is intended to be called whenever the
884 // CV's have been changed in some drastic way, and it's
885 // safest just to recompute everything.
886 ////////////////////////////////////////////////////////////////////
887 void HermiteCurve::
888 recompute_basis() {
889  int n;
890  for (n = 0; n < (int)_segs.size(); n++) {
891  if (_points[n]._type==HC_CUT) {
892  BezierSeg seg;
893  seg._v[0] = seg._v[1] = seg._v[2] = seg._v[3] = _points[n]._p;
894  get_curveseg(n)->bezier_basis(seg);
895  } else {
896  const HermiteCurveCV &p1 = _points[n];
897  HermiteCurveCV p2(_points[n+1]);
898  if (_curve_type == PCT_HPR) {
899  wrap_hpr(p1._p, p2._p);
900  }
901  get_curveseg(n)->hermite_basis(p1, p2, get_tlength(n));
902  }
903  }
904 }
905 
906 
907 ////////////////////////////////////////////////////////////////////
908 // Function: HermiteCurve::register_with_factory
909 // Access: Public, Static
910 // Description: Initializes the factory for reading these things from
911 // Bam files.
912 ////////////////////////////////////////////////////////////////////
913 void HermiteCurve::
915  BamReader::get_factory()->register_factory(get_class_type(), make_HermiteCurve);
916 }
917 
918 ////////////////////////////////////////////////////////////////////
919 // Function: HermiteCurve::make_HermiteCurve
920 // Access: Protected
921 // Description: Factory method to generate an object of this type.
922 ////////////////////////////////////////////////////////////////////
923 TypedWritable *HermiteCurve::
924 make_HermiteCurve(const FactoryParams &params) {
925  HermiteCurve *me = new HermiteCurve;
926  DatagramIterator scan;
927  BamReader *manager;
928 
929  parse_params(params, scan, manager);
930  me->fillin(scan, manager);
931  return me;
932 }
933 
934 ////////////////////////////////////////////////////////////////////
935 // Function: HermiteCurve::write_datagram
936 // Access: Protected, Virtual
937 // Description: Function to write the important information in
938 // the particular object to a Datagram
939 ////////////////////////////////////////////////////////////////////
940 void HermiteCurve::
941 write_datagram(BamWriter *manager, Datagram &me) {
942  PiecewiseCurve::write_datagram(manager, me);
943 
944  me.add_uint32(_points.size());
945  size_t i;
946  for (i = 0; i < _points.size(); i++) {
947  _points[i].write_datagram(manager, me);
948  }
949 }
950 
951 ////////////////////////////////////////////////////////////////////
952 // Function: HermiteCurve::fillin
953 // Access: Protected
954 // Description: Function that reads out of the datagram (or asks
955 // manager to read) all of the data that is needed to
956 // re-create this object and stores it in the appropiate
957 // place
958 ////////////////////////////////////////////////////////////////////
959 void HermiteCurve::
960 fillin(DatagramIterator &scan, BamReader *manager) {
961  PiecewiseCurve::fillin(scan, manager);
962 
963  size_t num_points = scan.get_uint32();
964  _points.reserve(num_points);
965  size_t i;
966  for (i = 0; i < num_points; i++) {
967  HermiteCurveCV cv;
968  cv.fillin(scan, manager);
969  _points.push_back(cv);
970  }
971 }
bool remove_cv(int n)
Removes the given CV from the curve.
PN_int8 get_int8()
Extracts a signed 8-bit integer.
This is the base class for all three-component vectors and points.
Definition: lvecBase3.h:105
void add_string(const string &str)
Adds a variable-length string to the datagram.
Definition: datagram.I:351
void remove_all_curvesegs()
Removes all curve segments from the curve.
PN_stdfloat get_cv_tstart(int n) const
Returns the starting point in parametric space of the given CV.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:122
A virtual base class for parametric curves.
int insert_cv(PN_stdfloat t)
Inserts a new CV at the given parametric point along the curve.
bool insert_curveseg(int ti, ParametricCurve *seg, PN_stdfloat tlength)
Inserts a new curve segment at the indicated index.
void add_int8(PN_int8 value)
Adds a signed 8-bit integer to the datagram.
Definition: datagram.I:128
int get_cv_type(int n) const
Returns the given CV&#39;s continuity type, HC_CUT, HC_FREE, HC_G1, or HC_SMOOTH, or 0 if there is no suc...
bool set_cv_name(int n, const char *name)
Changes the name associated with a particular CV.
void hermite_basis(const HermiteCurveCV &cv0, const HermiteCurveCV &cv1, PN_stdfloat tlength=1.0f)
Defines the curve segment as a Hermite.
bool set_cv_out(int n, PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Changes the given CV&#39;s out tangent.
void fillin(DatagramIterator &scan, BamReader *manager)
Function that reads out of the datagram (or asks manager to read) all of the data that is needed to r...
int append_cv(int type, PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Adds a new CV to the end of the curve.
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:37
void bezier_basis(const BezierSeg &seg)
Defines the curve segment as a Bezier.
virtual bool convert_to_hermite(HermiteCurve *hc) const
Stores an equivalent curve representation in the indicated Hermite curve, if possible.
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:73
PN_uint32 get_uint32()
Extracts an unsigned 32-bit integer.
bool set_cv_point(int n, PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Changes the given CV&#39;s position.
int get_num_cvs() const
Returns the number of CV&#39;s in the curve.
void set_in(const LVecBase3 &in)
Sets the CV&#39;s in tangent.
virtual bool get_pt(PN_stdfloat t, LVecBase3 &point, LVecBase3 &tangent) const
Simultaneously returns the point and tangent of the curve at a given parametric point t...
A parametric curve defined by a sequence of control vertices, each with an in and out tangent...
Definition: hermiteCurve.h:88
string get_string()
Extracts a variable-length string.
A CubicCurveseg is any curve that can be completely described by four 4-valued basis vectors...
Definition: cubicCurveseg.h:58
virtual PN_stdfloat get_max_t() const
Returns the upper bound of t for the entire curve.
PN_stdfloat get_tlength(int ti) const
Returns the parametric length of the given segment of the curve.
string get_cv_name(int n) const
Returns the name of the given CV, or NULL.
void set_out(const LVecBase3 &out)
Sets the CV&#39;s out tangent.
void set_type(int type)
Sets the continuity type of the CV.
static void register_with_read_factory()
Initializes the factory for reading these things from Bam files.
void remove_all_cvs()
Removes all CV&#39;s from the curve.
void format_egg(ostream &out, int indent, int num_dimensions, bool show_in, bool show_out, PN_stdfloat scale_in, PN_stdfloat scale_out) const
Formats the CV for output to an egg file.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:40
const LVecBase3 & get_cv_in(int n) const
Returns the in tangent of the given CV.
bool set_tlength(int ti, PN_stdfloat tlength)
Sets the parametric length of the given segment of the curve.
bool set_cv_type(int n, int type)
Changes the given CV&#39;s continuity type.
void register_factory(TypeHandle handle, CreateFunc *func)
Registers a new kind of thing the Factory will be able to create.
Definition: factory.I:90
const LVecBase3 & get_cv_point(int n) const
Returns the position of the given CV.
virtual bool rebuild_curveseg(int rtype0, PN_stdfloat t0, const LVecBase4 &v0, int rtype1, PN_stdfloat t1, const LVecBase4 &v1, int rtype2, PN_stdfloat t2, const LVecBase4 &v2, int rtype3, PN_stdfloat t3, const LVecBase4 &v3)
Rebuilds the current curve segment (as selected by the most recent call to find_curve()) according to...
This is the base class for all three-component vectors and points.
Definition: lvecBase4.h:111
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:213
bool set_cv_tstart(int n, PN_stdfloat tstart)
Changes the given CV&#39;s parametric starting time.
A single CV of a Hermite curve.
Definition: hermiteCurve.h:52
void add_uint32(PN_uint32 value)
Adds an unsigned 32-bit integer to the datagram.
Definition: datagram.I:192
void set_name(const string &name)
Sets the name associated with the CV.
A class to retrieve the individual data elements previously stored in a Datagram. ...
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
void write_datagram(BamWriter *manager, Datagram &me) const
Function to write the important information in the particular object to a Datagram.
bool set_cv_in(int n, PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Changes the given CV&#39;s in tangent.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:43
const LVecBase3 & get_cv_out(int n) const
Returns the out tangent of the given CV.
bool remove_curveseg(int ti)
Removes the given curve segment from the curve and frees it.
PN_stdfloat get_tstart(int ti) const
Returns the parametric start of the given segment of the curve.
virtual bool is_valid() const
Returns true if the curve is defined.
int get_curve_type() const
Returns the flag indicating the use to which the curve is intended to be put.