From f020b438fce7b543c0ced2902c97044f9e35f86e Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 6 Mar 2001 05:32:12 +0000 Subject: [PATCH] *** empty log message *** --- panda/src/parametrics/nurbsCurveDrawer.cxx | 18 +- panda/src/parametrics/nurbsCurveInterface.cxx | 2 +- panda/src/parametrics/nurbsCurveInterface.h | 2 - panda/src/parametrics/parametricCurve.cxx | 51 ++- panda/src/parametrics/parametricCurve.h | 8 + .../parametrics/parametricCurveCollection.I | 26 ++ .../parametrics/parametricCurveCollection.cxx | 361 +++++++++++++++--- .../parametrics/parametricCurveCollection.h | 17 + .../src/parametrics/parametricCurveDrawer.cxx | 22 +- panda/src/parametrics/piecewiseCurve.cxx | 6 +- panda/src/parametrics/piecewiseCurve.h | 13 +- 11 files changed, 442 insertions(+), 84 deletions(-) diff --git a/panda/src/parametrics/nurbsCurveDrawer.cxx b/panda/src/parametrics/nurbsCurveDrawer.cxx index a67ab5510b..2e533e6633 100644 --- a/panda/src/parametrics/nurbsCurveDrawer.cxx +++ b/panda/src/parametrics/nurbsCurveDrawer.cxx @@ -91,26 +91,22 @@ set_hull_color(float r, float g, float b) { //////////////////////////////////////////////////////////////////// bool NurbsCurveDrawer:: draw() { + // First, draw the curve itself. + if (!ParametricCurveDrawer::draw()) { + return false; + } + ParametricCurve *curve = (ParametricCurve *)NULL; NurbsCurveInterface *nurbs = (NurbsCurveInterface *)NULL; if (_curves != (ParametricCurveCollection *)NULL) { curve = _curves->get_default_curve(); - } - if (curve != (ParametricCurve *)NULL) { - nurbs = curve->get_nurbs_interface(); - if (nurbs != (NurbsCurveInterface *)NULL) { - // Make sure the curve is fresh. - nurbs->recompute(); + if (curve != (ParametricCurve *)NULL) { + nurbs = curve->get_nurbs_interface(); } } - // First, draw the curve itself. - if (!ParametricCurveDrawer::draw()) { - return false; - } - if (nurbs == (NurbsCurveInterface *)NULL) { // The rest of this depends on having an actual NURBS curve. return true; diff --git a/panda/src/parametrics/nurbsCurveInterface.cxx b/panda/src/parametrics/nurbsCurveInterface.cxx index 4c0c340893..963fc44349 100644 --- a/panda/src/parametrics/nurbsCurveInterface.cxx +++ b/panda/src/parametrics/nurbsCurveInterface.cxx @@ -168,5 +168,5 @@ convert_to_nurbs(ParametricCurve *nc) const { nurbs->set_knot(i, get_knot(i)); } - return nurbs->recompute(); + return nc->recompute(); } diff --git a/panda/src/parametrics/nurbsCurveInterface.h b/panda/src/parametrics/nurbsCurveInterface.h index 4e507de15f..3aa42e379e 100644 --- a/panda/src/parametrics/nurbsCurveInterface.h +++ b/panda/src/parametrics/nurbsCurveInterface.h @@ -52,8 +52,6 @@ PUBLISHED: virtual bool set_knot(int n, float t)=0; virtual float get_knot(int n) const=0; - virtual bool recompute()=0; - void write_cv(ostream &out, int n) const; diff --git a/panda/src/parametrics/parametricCurve.cxx b/panda/src/parametrics/parametricCurve.cxx index 8c0c78324e..d53029e817 100644 --- a/panda/src/parametrics/parametricCurve.cxx +++ b/panda/src/parametrics/parametricCurve.cxx @@ -263,6 +263,53 @@ find_length(float start_t, float length_offset) const { return max_t; } +//////////////////////////////////////////////////////////////////// +// Function: ParametricCurve::adjust_point +// Access: Published, Virtual +// Description: 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. +//////////////////////////////////////////////////////////////////// +bool ParametricCurve:: +adjust_point(float, float, float, float) { + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: ParametricCurve::adjust_tangent +// Access: Published, Virtual +// Description: Recomputes the curve such that it has the tangent +// (tx, ty, tz) at time t, but keeps the same position +// at the point. +//////////////////////////////////////////////////////////////////// +bool ParametricCurve:: +adjust_tangent(float, float, float, float) { + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: ParametricCurve::adjust_pt +// Access: Published, Virtual +// Description: Recomputes the curve such that it passes through the +// point (px, py, pz) with the tangent (tx, ty, tz). +//////////////////////////////////////////////////////////////////// +bool ParametricCurve:: +adjust_pt(float, float, float, float, float, float, float) { + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: ParametricCurve::recompute +// Access: Published, Virtual +// Description: Recalculates the curve, if necessary. Returns +// true if the resulting curve is valid, false +// otherwise. +//////////////////////////////////////////////////////////////////// +bool ParametricCurve:: +recompute() { + return is_valid(); +} + //////////////////////////////////////////////////////////////////// // Function: ParametricCurve::stitch // Access: Published, Virtual @@ -547,9 +594,7 @@ convert_to_nurbs(ParametricCurve *nc) const { } } - nurbs->recompute(); - - return nc->is_valid(); + return nc->recompute(); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/parametrics/parametricCurve.h b/panda/src/parametrics/parametricCurve.h index 055cd4deda..42a4e2f530 100644 --- a/panda/src/parametrics/parametricCurve.h +++ b/panda/src/parametrics/parametricCurve.h @@ -72,6 +72,14 @@ PUBLISHED: virtual bool get_pt(float t, LVecBase3f &point, LVecBase3f &tangent) const=0; virtual bool get_2ndtangent(float t, LVecBase3f &tangent2) const=0; + virtual bool adjust_point(float t, float px, float py, float pz); + virtual bool adjust_tangent(float t, float tx, float ty, float tz); + virtual bool adjust_pt(float t, + float px, float py, float pz, + float tx, float ty, float tz); + + virtual bool recompute(); + virtual bool stitch(const ParametricCurve *a, const ParametricCurve *b); bool write_egg(Filename filename, CoordinateSystem cs = CS_default); diff --git a/panda/src/parametrics/parametricCurveCollection.I b/panda/src/parametrics/parametricCurveCollection.I index 510c6be420..68c3e7544e 100644 --- a/panda/src/parametrics/parametricCurveCollection.I +++ b/panda/src/parametrics/parametricCurveCollection.I @@ -73,3 +73,29 @@ evaluate_hpr(float t, LVecBase3f &hpr) const { LVecBase3f xyz; return evaluate(t, xyz, hpr); } + +//////////////////////////////////////////////////////////////////// +// Function: ParametricCurveCollection::adjust_xyz +// Access: Published +// Description: Adjust the XYZ curve at the indicated time to the new +// value. The curve shape will change correspondingly. +// Returns true if successful, false if unable to make +// the adjustment for some reason. +//////////////////////////////////////////////////////////////////// +INLINE bool ParametricCurveCollection:: +adjust_xyz(float t, float x, float y, float z) { + return adjust_xyz(t, LVecBase3f(x, y, z)); +} + +//////////////////////////////////////////////////////////////////// +// Function: ParametricCurveCollection::adjust_hpr +// Access: Published +// Description: Adjust the HPR curve at the indicated time to the new +// value. The curve shape will change correspondingly. +// Returns true if successful, false if unable to make +// the adjustment for some reason. +//////////////////////////////////////////////////////////////////// +INLINE bool ParametricCurveCollection:: +adjust_hpr(float t, float h, float p, float r) { + return adjust_hpr(t, LVecBase3f(h, p, r)); +} diff --git a/panda/src/parametrics/parametricCurveCollection.cxx b/panda/src/parametrics/parametricCurveCollection.cxx index 4d32d0dda5..7f17621cc3 100644 --- a/panda/src/parametrics/parametricCurveCollection.cxx +++ b/panda/src/parametrics/parametricCurveCollection.cxx @@ -13,6 +13,7 @@ #include #include #include +#include //////////////////////////////////////////////////////////////////// // Function: ParametricCurveCollection::Constructor @@ -30,15 +31,23 @@ ParametricCurveCollection() { //////////////////////////////////////////////////////////////////// void ParametricCurveCollection:: add_curve(ParametricCurve *curve) { + prepare_add_curve(curve); _curves.push_back(curve); + redraw(); +} - DrawerList::iterator di; - for (di = _drawers.begin(); di != _drawers.end(); ++di) { - ParametricCurveDrawer *drawer = (*di); - curve->register_drawer(drawer); - - drawer->redraw(); - } +//////////////////////////////////////////////////////////////////// +// Function: ParametricCurveCollection::add_curve +// Access: Published +// Description: Adds a new ParametricCurve to the collection at the +// indicated index. +//////////////////////////////////////////////////////////////////// +void ParametricCurveCollection:: +add_curve(ParametricCurve *curve, int index) { + prepare_add_curve(curve); + index = max(min(index, (int)_curves.size()), 0); + _curves.insert(_curves.begin() + index, curve); + redraw(); } //////////////////////////////////////////////////////////////////// @@ -53,11 +62,7 @@ add_curves(Node *node) { int num_curves = r_add_curves(node); if (num_curves > 0) { - DrawerList::iterator di; - for (di = _drawers.begin(); di != _drawers.end(); ++di) { - ParametricCurveDrawer *drawer = (*di); - drawer->redraw(); - } + redraw(); } return num_curves; @@ -99,15 +104,9 @@ void ParametricCurveCollection:: remove_curve(int index) { nassertv(index >= 0 && index < (int)_curves.size()); PT(ParametricCurve) curve = _curves[index]; + prepare_remove_curve(curve); _curves.erase(_curves.begin() + index); - - DrawerList::iterator di; - for (di = _drawers.begin(); di != _drawers.end(); ++di) { - ParametricCurveDrawer *drawer = (*di); - curve->unregister_drawer(drawer); - - drawer->redraw(); - } + redraw(); } //////////////////////////////////////////////////////////////////// @@ -134,18 +133,14 @@ has_curve(ParametricCurve *curve) const { //////////////////////////////////////////////////////////////////// void ParametricCurveCollection:: clear() { - DrawerList::iterator di; - for (di = _drawers.begin(); di != _drawers.end(); ++di) { - ParametricCurveDrawer *drawer = (*di); - ParametricCurves::iterator ci; - for (ci = _curves.begin(); ci != _curves.end(); ++ci) { - ParametricCurve *curve = (*ci); - curve->unregister_drawer(drawer); - } - - drawer->redraw(); + ParametricCurves::iterator ci; + for (ci = _curves.begin(); ci != _curves.end(); ++ci) { + ParametricCurve *curve = (*ci); + prepare_remove_curve(curve); } _curves.clear(); + + redraw(); } //////////////////////////////////////////////////////////////////// @@ -157,7 +152,6 @@ void ParametricCurveCollection:: clear_timewarps() { PT(ParametricCurve) xyz_curve = (ParametricCurve *)NULL; PT(ParametricCurve) hpr_curve = (ParametricCurve *)NULL; - ParametricCurves discard; ParametricCurves::iterator ci; for (ci = _curves.begin(); ci != _curves.end(); ++ci) { @@ -168,7 +162,7 @@ clear_timewarps() { if (xyz_curve == (ParametricCurve *)NULL) { xyz_curve = curve; } else { - discard.push_back(curve); + prepare_remove_curve(curve); } break; @@ -176,12 +170,12 @@ clear_timewarps() { if (hpr_curve == (ParametricCurve *)NULL) { hpr_curve = curve; } else { - discard.push_back(curve); + prepare_remove_curve(curve); } break; default: - discard.push_back(curve); + prepare_remove_curve(curve); } } @@ -192,18 +186,7 @@ clear_timewarps() { _curves.push_back(hpr_curve); } - // Properly unregister all the curves we're discarding. - DrawerList::iterator di; - for (di = _drawers.begin(); di != _drawers.end(); ++di) { - ParametricCurveDrawer *drawer = (*di); - ParametricCurves::iterator ci; - for (ci = discard.begin(); ci != discard.end(); ++ci) { - ParametricCurve *curve = (*ci); - curve->unregister_drawer(drawer); - } - - drawer->redraw(); - } + redraw(); } //////////////////////////////////////////////////////////////////// @@ -288,6 +271,27 @@ get_num_timewarps() const { return count; } +//////////////////////////////////////////////////////////////////// +// Function: ParametricCurveCollection::get_timewarp_curve +// Access: Published +// Description: Returns the nth timewarp curve in the collection. +//////////////////////////////////////////////////////////////////// +ParametricCurve *ParametricCurveCollection:: +get_timewarp_curve(int n) const { + ParametricCurves::const_iterator ci; + for (ci = _curves.begin(); ci != _curves.end(); ++ci) { + ParametricCurve *curve = (*ci); + if (curve->get_curve_type() == PCT_T) { + if (n == 0) { + return curve; + } + n--; + } + } + nassertr(false, (ParametricCurve *)NULL); + return (ParametricCurve *)NULL; +} + //////////////////////////////////////////////////////////////////// // Function: ParametricCurveCollection::make_even // Access: Published @@ -320,21 +324,43 @@ make_even(float max_t, float segments_per_unit) { // approximately the same length as all the others. CurveFitter fitter; - int num_segments = (int)floor(segments_per_unit * xyz_curve->get_max_t() + 0.5); + int num_segments = max(1, (int)floor(segments_per_unit * xyz_curve->get_max_t() + 0.5)); + + if (parametrics_cat.is_debug()) { + parametrics_cat.debug() + << "Calculating length of curve.\n"; + } float net_length = xyz_curve->calc_length(); float segment_length = net_length / (float)num_segments; + if (parametrics_cat.is_debug()) { + parametrics_cat.debug() + << "Curve has total length " << net_length << "; dividing into " + << num_segments << " segments of " << segment_length << " units each.\n"; + } + float last_t = 0.0; fitter.add_xyz(0.0, LVecBase3f(last_t, 0.0, 0.0)); for (int i = 0; i < num_segments; i++) { float next_t = xyz_curve->find_length(last_t, segment_length); - fitter.add_xyz((float)(i + 1) / (num_segments + 1) * max_t, + fitter.add_xyz((float)(i + 1) / num_segments * max_t, LVecBase3f(next_t, 0.0, 0.0)); + + if (parametrics_cat.is_spam()) { + parametrics_cat.spam() + << "Point " << i << " is at " << next_t << "\n"; + } + last_t = next_t; } + if (parametrics_cat.is_debug()) { + parametrics_cat.debug() + << "Done computing segments.\n"; + } + fitter.compute_tangents(1); PT(ParametricCurveCollection) fit = fitter.make_nurbs(); ParametricCurve *t_curve = fit->get_xyz_curve(); @@ -343,6 +369,96 @@ make_even(float max_t, float segments_per_unit) { add_curve(t_curve); } +//////////////////////////////////////////////////////////////////// +// Function: ParametricCurveCollection::face_forward +// Access: Published +// Description: Discards the existing HPR curve and generates a new +// one that looks in the direction of travel along the +// XYZ curve, based on the XYZ curve's tangent at each +// point. +//////////////////////////////////////////////////////////////////// +void ParametricCurveCollection:: +face_forward(float segments_per_unit) { + ParametricCurve *xyz_curve = get_xyz_curve(); + if (xyz_curve == (ParametricCurve *)NULL) { + parametrics_cat.error() + << "No XYZ curve for face_forward().\n"; + return; + } + + // Eliminate all the old hpr curves, and also take note of the index + // number of the first XYZ curve. + int xyz_index = -1; + ParametricCurves::const_iterator ci; + ParametricCurves new_curves; + + for (ci = _curves.begin(); ci != _curves.end(); ++ci) { + ParametricCurve *curve = (*ci); + if (curve->get_curve_type() == PCT_HPR) { + prepare_remove_curve(curve); + } else { + if (curve->get_curve_type() == PCT_XYZ && xyz_index == -1) { + xyz_index = (ci - _curves.begin()); + } + new_curves.push_back(curve); + } + } + _curves.swap(new_curves); + + // Now divvy up the XYZ curve into num_segments sections, of equal + // length in parametric time (based on the timewarp curves). + CurveFitter fitter; + + float max_t = get_max_t(); + int num_segments = (int)floor(segments_per_unit * max_t + 0.5); + + LVecBase3f hpr(0.0, 0.0, 0.0); + + // We compute the first HPR point a little point into the beginning + // of the curve, instead of at 0.0, because the tangent at 0.0 is + // likely to be zero. + determine_hpr(0.001, xyz_curve, hpr); + fitter.add_hpr(0.0, hpr); + + for (int i = 0; i < num_segments; i++) { + float t = (float)(i + 1) / num_segments * max_t; + determine_hpr(t, xyz_curve, hpr); + fitter.add_hpr(t, hpr); + } + + fitter.wrap_hpr(); + fitter.compute_tangents(1); + PT(ParametricCurveCollection) fit = fitter.make_nurbs(); + ParametricCurve *hpr_curve = fit->get_hpr_curve(); + nassertv(hpr_curve != (ParametricCurve *)NULL); + add_curve(hpr_curve, xyz_index + 1); +} + +//////////////////////////////////////////////////////////////////// +// Function: ParametricCurveCollection::reset_max_t +// Access: Published +// Description: Adjusts the apparent length of the curve by applying +// a new timewarp that maps the range [0..max_t] to the +// range [0..get_max_t()]. After this call, the curve +// collection will contain one more timewarp curve, and +// get_max_t() will return the given max_t value. +//////////////////////////////////////////////////////////////////// +void ParametricCurveCollection:: +reset_max_t(float max_t) { + // Define a linear NURBS curve. + PT(NurbsCurve) nurbs = new NurbsCurve; + nurbs->set_curve_type(PCT_T); + nurbs->set_order(2); + nurbs->append_cv(LVecBase3f(0.0, 0.0, 0.0)); + nurbs->append_cv(LVecBase3f(get_max_t(), 0.0, 0.0)); + nurbs->set_knot(0, 0.0); + nurbs->set_knot(1, 0.0); + nurbs->set_knot(2, max_t); + nurbs->set_knot(3, max_t); + nurbs->recompute(); + add_curve(nurbs); +} + //////////////////////////////////////////////////////////////////// // Function: ParametricCurveCollection::evaluate // Access: Published @@ -470,6 +586,72 @@ evaluate_t(float t) const { return t0; } +//////////////////////////////////////////////////////////////////// +// Function: ParametricCurveCollection::adjust_xyz +// Access: Published +// Description: Adjust the XYZ curve at the indicated time to the new +// value. The curve shape will change correspondingly. +// Returns true if successful, false if unable to make +// the adjustment for some reason. +//////////////////////////////////////////////////////////////////// +bool ParametricCurveCollection:: +adjust_xyz(float t, const LVecBase3f &xyz) { + ParametricCurve *xyz_curve = get_xyz_curve(); + if (xyz_curve == (ParametricCurve *)NULL) { + return false; + } + + float t0 = evaluate_t(t); + if (t0 >= 0.0 && t < xyz_curve->get_max_t()) { + return xyz_curve->adjust_point(t, xyz[0], xyz[1], xyz[2]); + } + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: ParametricCurveCollection::adjust_hpr +// Access: Published +// Description: Adjust the HPR curve at the indicated time to the new +// value. The curve shape will change correspondingly. +// Returns true if successful, false if unable to make +// the adjustment for some reason. +//////////////////////////////////////////////////////////////////// +bool ParametricCurveCollection:: +adjust_hpr(float t, const LVecBase3f &hpr) { + ParametricCurve *hpr_curve = get_hpr_curve(); + if (hpr_curve == (ParametricCurve *)NULL) { + return false; + } + + float t0 = evaluate_t(t); + if (t0 >= 0.0 && t < hpr_curve->get_max_t()) { + return hpr_curve->adjust_point(t, hpr[0], hpr[1], hpr[2]); + } + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: ParametricCurveCollection::recompute +// Access: Published +// Description: Ensures all the curves are freshly computed and +// up-to-date. Returns true if everything is valid, +// false if at least one curve is incorrect. +//////////////////////////////////////////////////////////////////// +bool ParametricCurveCollection:: +recompute() { + bool all_ok = true; + + ParametricCurves::iterator ci; + for (ci = _curves.begin(); ci != _curves.end(); ++ci) { + ParametricCurve *curve = (*ci); + if (!curve->recompute()) { + all_ok = false; + } + } + + return all_ok; +} + //////////////////////////////////////////////////////////////////// // Function: ParametricCurveCollection::stitch // Access: Published @@ -660,13 +842,8 @@ r_add_curves(Node *node) { if (node->is_of_type(ParametricCurve::get_class_type())) { ParametricCurve *curve = DCAST(ParametricCurve, node); + prepare_add_curve(curve); _curves.push_back(curve); - - DrawerList::iterator di; - for (di = _drawers.begin(); di != _drawers.end(); ++di) { - ParametricCurveDrawer *drawer = (*di); - curve->register_drawer(drawer); - } num_curves++; } @@ -719,3 +896,79 @@ unregister_drawer(ParametricCurveDrawer *drawer) { curve->unregister_drawer(drawer); } } + +//////////////////////////////////////////////////////////////////// +// Function: ParametricCurveCollection::determine_hpr +// Access: Private +// Description: Computes the orientation at the given point in time, +// based on the tangent of the XYZ curve. Returns true +// if the orientation can be determined, or false if it +// cannot (in which case hpr is left unchanged). +//////////////////////////////////////////////////////////////////// +bool ParametricCurveCollection:: +determine_hpr(float t, ParametricCurve *xyz_curve, LVecBase3f &hpr) const { + float t0 = evaluate_t(t); + + LVector3f tangent; + if (!xyz_curve->get_tangent(t0, tangent)) { + return false; + } + + if (tangent.length_squared() == 0.0) { + return false; + } + + LMatrix3f mat; + look_at(mat, tangent); + + LVecBase3f scale; + decompose_matrix(mat, scale, hpr); + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: ParametricCurveCollection::prepare_add_curve +// Access: Private +// Description: Registers the curve with the list of drawers that +// share this collection, in preparation for adding it +// to the _curves list. +//////////////////////////////////////////////////////////////////// +void ParametricCurveCollection:: +prepare_add_curve(ParametricCurve *curve) { + DrawerList::iterator di; + for (di = _drawers.begin(); di != _drawers.end(); ++di) { + ParametricCurveDrawer *drawer = (*di); + curve->register_drawer(drawer); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: ParametricCurveCollection::prepare_remove_curve +// Access: Private +// Description: Unregisters the curve with the list of drawers that +// share this collection, in preparation for removing it +// from the _curves list. +//////////////////////////////////////////////////////////////////// +void ParametricCurveCollection:: +prepare_remove_curve(ParametricCurve *curve) { + DrawerList::iterator di; + for (di = _drawers.begin(); di != _drawers.end(); ++di) { + ParametricCurveDrawer *drawer = (*di); + curve->unregister_drawer(drawer); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: ParametricCurveCollection::redraw +// Access: Private +// Description: Calls redraw() on all drawers that share this +// collection. +//////////////////////////////////////////////////////////////////// +void ParametricCurveCollection:: +redraw() { + DrawerList::iterator di; + for (di = _drawers.begin(); di != _drawers.end(); ++di) { + ParametricCurveDrawer *drawer = (*di); + drawer->redraw(); + } +} diff --git a/panda/src/parametrics/parametricCurveCollection.h b/panda/src/parametrics/parametricCurveCollection.h index a6776e6612..13375e9853 100644 --- a/panda/src/parametrics/parametricCurveCollection.h +++ b/panda/src/parametrics/parametricCurveCollection.h @@ -35,6 +35,7 @@ PUBLISHED: INLINE ~ParametricCurveCollection(); void add_curve(ParametricCurve *curve); + void add_curve(ParametricCurve *curve, int index); int add_curves(Node *node); bool remove_curve(ParametricCurve *curve); void remove_curve(int index); @@ -49,10 +50,13 @@ PUBLISHED: ParametricCurve *get_hpr_curve() const; ParametricCurve *get_default_curve() const; int get_num_timewarps() const; + ParametricCurve *get_timewarp_curve(int n) const; INLINE float get_max_t() const; void make_even(float max_t, float segments_per_unit); + void face_forward(float segments_per_unit); + void reset_max_t(float max_t); bool evaluate(float t, LVecBase3f &xyz, LVecBase3f &hpr) const; bool evaluate(float t, LMatrix4f &result, CoordinateSystem cs = CS_default) const; @@ -61,6 +65,13 @@ PUBLISHED: INLINE bool evaluate_xyz(float t, LVecBase3f &xyz) const; INLINE bool evaluate_hpr(float t, LVecBase3f &hpr) const; + INLINE bool adjust_xyz(float t, float x, float y, float z); + bool adjust_xyz(float t, const LVecBase3f &xyz); + INLINE bool adjust_hpr(float t, float h, float p, float r); + bool adjust_hpr(float t, const LVecBase3f &xyz); + + bool recompute(); + bool stitch(const ParametricCurveCollection *a, const ParametricCurveCollection *b); @@ -75,6 +86,12 @@ public: void register_drawer(ParametricCurveDrawer *drawer); void unregister_drawer(ParametricCurveDrawer *drawer); +private: + bool determine_hpr(float t, ParametricCurve *xyz_curve, LVecBase3f &hpr) const; + void prepare_add_curve(ParametricCurve *curve); + void prepare_remove_curve(ParametricCurve *curve); + void redraw(); + private: typedef vector ParametricCurves; ParametricCurves _curves; diff --git a/panda/src/parametrics/parametricCurveDrawer.cxx b/panda/src/parametrics/parametricCurveDrawer.cxx index 5e3dbeeac8..67fe683d74 100644 --- a/panda/src/parametrics/parametricCurveDrawer.cxx +++ b/panda/src/parametrics/parametricCurveDrawer.cxx @@ -297,16 +297,26 @@ draw() { // First, remove the old drawing, if any. hide(); + _drawn = true; + // If there's no curve, draw nothing and return false. - if (_curves == (ParametricCurveCollection *)NULL || - _curves->get_default_curve() == (ParametricCurve *)NULL) { + if (_curves == (ParametricCurveCollection *)NULL) { + return false; + } + + ParametricCurve *xyz_curve = _curves->get_default_curve(); + if (xyz_curve == (ParametricCurve *)NULL) { return false; } // Otherwise, let's go to town! + + // Make sure the curve(s) are fresh. + _curves->recompute(); + int total_segs = (int)floor(_curves->get_max_t() * _num_segs + 0.5); - float max_t = get_max_t(); + float max_t = xyz_curve->get_max_t(); float scale = max_t / (float)(total_segs-1); float t; LVecBase3f point; @@ -318,7 +328,7 @@ draw() { for (i = 0; i < total_segs; i++) { t = (float)i * scale; - next_in = _curves->evaluate_xyz(t, point); + next_in = xyz_curve->get_point(t, point); if (!next_in || !last_in) { _lines.move_to(point); @@ -329,7 +339,9 @@ draw() { } _lines.create(_geom_node, _frame_accurate); - _drawn = true; + + max_t = get_max_t(); + scale = max_t / (float)(total_segs-1); // Now draw the time tick marks. if (_num_ticks > 0.0) { diff --git a/panda/src/parametrics/piecewiseCurve.cxx b/panda/src/parametrics/piecewiseCurve.cxx index b926b9c80a..227a419e9f 100644 --- a/panda/src/parametrics/piecewiseCurve.cxx +++ b/panda/src/parametrics/piecewiseCurve.cxx @@ -112,7 +112,7 @@ get_2ndtangent(float t, LVecBase3f &tangent2) const { //////////////////////////////////////////////////////////////////// // Function: PiecewiseCurve::adjust_point -// Access: Published +// Access: Published, Virtual // Description: 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. @@ -143,7 +143,7 @@ adjust_point(float t, //////////////////////////////////////////////////////////////////// // Function: PiecewiseCurve::adjust_tangent -// Access: Published +// Access: Published, Virtual // Description: Recomputes the curve such that it has the tangent // (tx, ty, tz) at time t, but keeps the same position // at the point. @@ -168,7 +168,7 @@ adjust_tangent(float t, //////////////////////////////////////////////////////////////////// // Function: PiecewiseCurve::adjust_pt -// Access: Published +// Access: Published, Virtual // Description: Recomputes the curve such that it passes through the // point (px, py, pz) with the tangent (tx, ty, tz). //////////////////////////////////////////////////////////////////// diff --git a/panda/src/parametrics/piecewiseCurve.h b/panda/src/parametrics/piecewiseCurve.h index e4ac6ce5bd..e2e3051fcd 100644 --- a/panda/src/parametrics/piecewiseCurve.h +++ b/panda/src/parametrics/piecewiseCurve.h @@ -22,6 +22,9 @@ PUBLISHED: PiecewiseCurve(); ~PiecewiseCurve(); +public: + // These functions are all inherited from ParametricCurve, and need + // not be re-published. virtual bool is_valid() const; virtual float get_max_t() const; @@ -30,11 +33,11 @@ PUBLISHED: virtual bool get_pt(float t, LVecBase3f &point, LVecBase3f &tangent) const; virtual bool get_2ndtangent(float t, LVecBase3f &tangent2) const; - bool adjust_point(float t, float px, float py, float pz); - bool adjust_tangent(float t, float tx, float ty, float tz); - bool adjust_pt(float t, - float px, float py, float pz, - float tx, float ty, float tz); + virtual bool adjust_point(float t, float px, float py, float pz); + virtual bool adjust_tangent(float t, float tx, float ty, float tz); + virtual bool adjust_pt(float t, + float px, float py, float pz, + float tx, float ty, float tz); public: int get_num_segs() const;