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, but keeps the same tangent value at that point.
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(), ComputeTangents() must be called to set up the tangents correctly (unless the tangents were defined as the points were added).
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...