Panda3D
 All Classes Functions Variables Enumerations
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 =
346  insert_curveseg(n, new CubicCurveseg, t - get_cv_tstart(n));
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());
415  remove_all_curvesegs();
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.
int get_num_cvs() const
Returns the number of CV&#39;s in the curve.
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
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.
void add_int8(PN_int8 value)
Adds a signed 8-bit integer to the datagram.
Definition: datagram.I:128
bool set_cv_name(int n, const char *name)
Changes the name associated with a particular CV.
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
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.
void set_in(const LVecBase3 &in)
Sets the CV&#39;s in tangent.
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
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.
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 wrap_hpr()
Resets each HPR data point so that the maximum delta between any two consecutive points is 180 degree...
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_point(int n) const
Returns the position of the given CV.
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...
PN_stdfloat get_cv_tstart(int n) const
Returns the starting point in parametric space of the given CV.
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
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
virtual bool convert_to_hermite(HermiteCurve *hc) const
Stores an equivalent curve representation in the indicated Hermite curve, if possible.
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. ...
const LVecBase3 & get_cv_out(int n) const
Returns the out tangent of the given CV.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
const LVecBase3 & get_cv_in(int n) const
Returns the in tangent of the given CV.
string get_cv_name(int n) const
Returns the name of the given CV, or NULL.
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
void write_datagram(BamWriter *manager, Datagram &me) const
Function to write the important information in the particular object to a Datagram.