27 ParametricCurveCollection::
28 ParametricCurveCollection() {
36 prepare_add_curve(curve);
37 _curves.push_back(curve);
46 prepare_add_curve(curve);
47 index = std::min(index, _curves.size());
48 _curves.insert(_curves.begin() + index, curve);
74 for (
int i = 0; curve_index == -1 && i < (int)_curves.size(); i++) {
75 if (_curves[i] == curve) {
80 if (curve_index == -1) {
97 nassertv(index < _curves.size());
99 prepare_remove_curve(curve);
100 _curves.erase(_curves.begin() + index);
111 nassertv(index < _curves.size());
112 prepare_remove_curve(_curves[index]);
113 prepare_add_curve(curve);
114 _curves[index] = curve;
124 ParametricCurves::const_iterator ci;
125 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
126 if (curve == (*ci)) {
138 ParametricCurves::iterator ci;
139 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
141 prepare_remove_curve(curve);
156 ParametricCurves::iterator ci;
157 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
162 if (xyz_curve ==
nullptr) {
165 prepare_remove_curve(curve);
170 if (hpr_curve ==
nullptr) {
173 prepare_remove_curve(curve);
178 prepare_remove_curve(curve);
183 _curves.push_back(xyz_curve);
185 if (hpr_curve !=
nullptr) {
186 _curves.push_back(hpr_curve);
197 get_xyz_curve()
const {
198 ParametricCurves::const_iterator ci;
199 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
213 get_hpr_curve()
const {
214 ParametricCurves::const_iterator ci;
215 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
230 get_default_curve()
const {
232 if (xyz_curve !=
nullptr) {
236 ParametricCurves::const_iterator ci;
237 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
249 int ParametricCurveCollection::
250 get_num_timewarps()
const {
253 ParametricCurves::const_iterator ci;
254 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
269 ParametricCurves::const_iterator ci;
270 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
279 nassert_raise(
"index out of range");
296 make_even(PN_stdfloat max_t, PN_stdfloat segments_per_unit) {
298 if (xyz_curve ==
nullptr) {
299 parametrics_cat.error()
300 <<
"No XYZ curve for make_even().\n";
310 int num_segments = std::max(1, (
int)cfloor(segments_per_unit * xyz_curve->
get_max_t() + 0.5f));
312 if (parametrics_cat.is_debug()) {
313 parametrics_cat.debug()
314 <<
"Calculating length of curve.\n";
318 PN_stdfloat segment_length = net_length / (PN_stdfloat)num_segments;
320 if (parametrics_cat.is_debug()) {
321 parametrics_cat.debug()
322 <<
"Curve has total length " << net_length <<
"; dividing into " 323 << num_segments <<
" segments of " << segment_length <<
" units each.\n";
326 PN_stdfloat last_t = 0.0f;
327 fitter.
add_xyz(0.0f, LVecBase3(last_t, 0.0f, 0.0f));
328 PN_stdfloat val_inc= max_t/num_segments;
329 PN_stdfloat val=val_inc;
331 for (
int i = 0; i < num_segments; i++,val+=val_inc) {
332 PN_stdfloat next_t = xyz_curve->
find_length(last_t, segment_length);
334 val, LVecBase3(next_t, 0.0f, 0.0f));
336 if (parametrics_cat.is_spam()) {
337 parametrics_cat.spam()
338 <<
"Point " << i <<
" is at " << next_t <<
"\n";
344 if (parametrics_cat.is_debug()) {
345 parametrics_cat.debug()
346 <<
"Done computing segments.\n";
352 nassertv(t_curve !=
nullptr);
365 if (xyz_curve ==
nullptr) {
366 parametrics_cat.error()
367 <<
"No XYZ curve for face_forward().\n";
374 ParametricCurves::const_iterator ci;
377 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
380 prepare_remove_curve(curve);
383 xyz_index = (ci - _curves.begin());
385 new_curves.push_back(curve);
388 _curves.swap(new_curves);
395 int num_segments = (int)cfloor(segments_per_unit * max_t + 0.5);
397 LVecBase3 hpr(0.0f, 0.0f, 0.0f);
402 determine_hpr(0.001, xyz_curve, hpr);
405 for (
int i = 0; i < num_segments; i++) {
406 PN_stdfloat t = (PN_stdfloat)(i + 1) / num_segments * max_t;
407 determine_hpr(t, xyz_curve, hpr);
415 nassertv(hpr_curve !=
nullptr);
429 nurbs->set_curve_type(PCT_T);
431 nurbs->append_cv(LVecBase3(0.0f, 0.0f, 0.0f));
432 nurbs->append_cv(LVecBase3(
get_max_t(), 0.0f, 0.0f));
433 nurbs->set_knot(0, 0.0f);
434 nurbs->set_knot(1, 0.0f);
435 nurbs->set_knot(2, max_t);
436 nurbs->set_knot(3, max_t);
452 evaluate(PN_stdfloat t, LVecBase3 &xyz, LVecBase3 &hpr)
const {
462 ParametricCurves::const_reverse_iterator ci;
463 for (ci = _curves.rbegin(); ci != _curves.rend(); ++ci) {
476 default_curve = curve;
480 if (!curve->get_point(t0, point)) {
487 if (xyz_curve ==
nullptr) {
488 xyz_curve = default_curve;
492 if (xyz_curve !=
nullptr) {
493 if (!xyz_curve->get_point(t0, xyz)) {
498 if (hpr_curve !=
nullptr) {
499 if (!hpr_curve->get_point(t0, hpr)) {
519 evaluate(PN_stdfloat t, LMatrix4 &result, CoordinateSystem cs)
const {
520 LVecBase3 xyz(0.0f, 0.0f, 0.0f);
521 LVecBase3 hpr(0.0f, 0.0f, 0.0f);
527 compose_matrix(result,
528 LVecBase3(1.0f, 1.0f, 1.0f),
529 LVecBase3(0.0f, 0.0f, 0.0f),
544 ParametricCurves::const_iterator ci;
545 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
549 if (!curve->get_point(t0, point)) {
567 if (xyz_curve ==
nullptr) {
572 if (t0 >= 0.0f && t < xyz_curve->
get_max_t()) {
573 return xyz_curve->
adjust_point(t, xyz[0], xyz[1], xyz[2]);
586 if (hpr_curve ==
nullptr) {
591 if (t0 >= 0.0f && t < hpr_curve->
get_max_t()) {
592 return hpr_curve->
adjust_point(t, hpr[0], hpr[1], hpr[2]);
605 ParametricCurves::iterator ci;
606 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
634 if (a_xyz !=
nullptr && b_xyz !=
nullptr) {
636 if (!new_xyz->stitch(a_xyz, b_xyz)) {
643 if (a_hpr !=
nullptr && b_hpr !=
nullptr) {
645 if (!new_hpr->stitch(a_hpr, b_hpr)) {
662 out <<
"1 ParametricCurve";
673 write(std::ostream &out,
int indent_level)
const {
674 ParametricCurves::const_iterator ci;
675 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
677 indent(out, indent_level) << *curve <<
"\n";
691 parametrics_cat.error()
692 <<
"Unable to write to " << filename <<
"\n";
704 if (cs == CS_default) {
705 cs = get_default_coordinate_system();
708 if (cs != CS_invalid) {
709 out <<
"<CoordinateSystem> { ";
737 ParametricCurves::iterator ci;
738 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
749 name += format_string(xyz_count);
757 name += format_string(hpr_count);
765 name += format_string(t_count);
771 curve->set_name(name);
774 if (!curve->
write_egg(out, filename, CS_invalid)) {
789 if (node->
is_of_type(ParametricCurve::get_class_type())) {
791 prepare_add_curve(curve);
792 _curves.push_back(curve);
797 for (
int i = 0; i < num_children; i++) {
815 _drawers.push_back(drawer);
817 ParametricCurves::iterator ci;
818 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
831 _drawers.remove(drawer);
833 ParametricCurves::iterator ci;
834 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
845 bool ParametricCurveCollection::
846 determine_hpr(PN_stdfloat t,
ParametricCurve *xyz_curve, LVecBase3 &hpr)
const {
850 if (!xyz_curve->get_tangent(t0, tangent)) {
854 if (tangent.length_squared() == 0.0f) {
859 look_at(mat, tangent);
861 LVecBase3 scale, shear;
862 return decompose_matrix(mat, scale, shear, hpr);
869 void ParametricCurveCollection::
871 DrawerList::iterator di;
872 for (di = _drawers.begin(); di != _drawers.end(); ++di) {
873 ParametricCurveDrawer *drawer = (*di);
882 void ParametricCurveCollection::
884 DrawerList::iterator di;
885 for (di = _drawers.begin(); di != _drawers.end(); ++di) {
886 ParametricCurveDrawer *drawer = (*di);
894 void ParametricCurveCollection::
bool adjust_hpr(PN_stdfloat t, PN_stdfloat h, PN_stdfloat p, PN_stdfloat r)
Adjust the HPR curve at the indicated time to the new value.
get_max_t
Returns the maximum T value associated with the *last* curve in the collection.
bool open_write(std::ofstream &stream, bool truncate=true) const
Opens the indicated ifstream for writing the file, if possible.
void insert_curve(size_t index, ParametricCurve *curve)
Adds a new ParametricCurve to the collection at the indicated index.
A basic node of the scene graph or data graph.
void register_drawer(ParametricCurveDrawer *drawer)
Registers a Drawer with this curve collection that will automatically be updated whenever the collect...
virtual bool adjust_point(PN_stdfloat t, PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz)
Recomputes the curve such that it passes through the point (px, py, pz) at time t,...
int r_add_curves(PandaNode *node)
The recursive implementation of add_curves().
PN_stdfloat evaluate_t(PN_stdfloat t) const
Determines the value of t that should be passed to the XYZ and HPR curves, after applying the given v...
A virtual base class for parametric curves.
void face_forward(PN_stdfloat segments_per_unit)
Discards the existing HPR curve and generates a new one that looks in the direction of travel along t...
virtual bool recompute()
Recalculates the curve, if necessary.
void register_drawer(ParametricCurveDrawer *drawer)
Registers a Drawer with this curve that will automatically be updated whenever the curve is modified,...
std::string get_basename_wo_extension() const
Returns the basename part of the filename, without the file extension.
bool has_curve(ParametricCurve *curve) const
Returns true if the indicated ParametricCurve appears in this collection, false otherwise.
PN_stdfloat find_length(PN_stdfloat start_t, PN_stdfloat length_offset) const
Returns the parametric value corresponding to the indicated distance along the curve from the startin...
get_num_curves
Returns the number of ParametricCurves in the collection.
void set_text()
Indicates that the filename represents a text file.
bool write_egg(Filename filename, CoordinateSystem cs=CS_default)
Writes an egg description of the nurbs curve to the specified output file.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
remove_curve
Removes the indicated ParametricCurve from the collection.
bool evaluate(PN_stdfloat t, LVecBase3 &xyz, LVecBase3 &hpr) const
Computes the position and rotation represented by the first XYZ and HPR curves in the collection at t...
void unregister_drawer(ParametricCurveDrawer *drawer)
Removes a previously registered drawer from the list of automatically- refreshed drawers.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void clear_timewarps()
Removes all the timewarp curves from the collection.
set_curve
Replaces the indicated ParametricCurve from the collection, by its index number.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void compute_tangents(PN_stdfloat scale)
Once a set of points has been built, and prior to calling MakeHermite() or MakeNurbs(),...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is a set of zero or more ParametricCurves, which may or may not be related.
get_num_children
Returns the number of child nodes this node has.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_timewarp_curve
Returns the nth timewarp curve in the collection.
The name of a file, such as a texture file or an Egg file.
int add_curves(PandaNode *node)
Adds all the curves found in the scene graph rooted at the given node.
get_hpr_curve
Returns the first HPR curve in the collection, if any, or NULL if there are none.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
void wrap_hpr()
Resets each HPR data point so that the maximum delta between any two consecutive points is 180 degree...
A Nonuniform Rational B-Spline.
void clear()
Removes all ParametricCurves from the collection.
bool adjust_xyz(PN_stdfloat t, PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Adjust the XYZ curve at the indicated time to the new value.
virtual PN_stdfloat get_max_t() const
Returns the upper bound of t for the entire curve.
bool recompute()
Ensures all the curves are freshly computed and up-to-date.
void add_hpr(PN_stdfloat t, const LVecBase3 &hpr)
Adds a single sample hpr.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void add_xyz(PN_stdfloat t, const LVecBase3 &xyz)
Adds a single sample xyz.
bool write_egg(Filename filename, CoordinateSystem cs=CS_default)
Writes an egg description of all the nurbs curves in the collection to the specified output file.
void set_curve_type(int type)
Sets the flag indicating the use to which the curve is intended to be put.
void make_even(PN_stdfloat max_t, PN_stdfloat segments_per_unit)
Discards all existing timewarp curves and recomputes a new timewarp curve that maps distance along th...
get_xyz_curve
Returns the first XYZ curve in the collection, if any, or NULL if there are none.
void add_curve(ParametricCurve *curve)
Adds a new ParametricCurve to the collection.
PN_stdfloat calc_length() const
Approximates the length of the entire curve to within a few decimal places.
void unregister_drawer(ParametricCurveDrawer *drawer)
Removes a previously registered drawer from the list of automatically- refreshed drawers.
void write(std::ostream &out, int indent_level=0) const
Writes a complete multi-line description of the ParametricCurveCollection to the indicated output str...
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
bool has_name() const
Returns true if the Namable has a nonempty name set, false if the name is empty.
get_child
Returns the nth child node of this node.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void output(std::ostream &out) const
Writes a brief one-line description of the ParametricCurveCollection to the indicated output stream.
bool stitch(const ParametricCurveCollection *a, const ParametricCurveCollection *b)
Regenerates this curve as one long curve: the first curve connected end-to- end with the second one.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_curve_type() const
Returns the flag indicating the use to which the curve is intended to be put.
void reset_max_t(PN_stdfloat max_t)
Adjusts the apparent length of the curve by applying a new timewarp that maps the range [0....