Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/parametrics/parametricCurveDrawer.cxx

Go to the documentation of this file.
00001 // Filename: parametricCurveDrawer.cxx
00002 // Created by:  drose (14Mar97)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 
00020 #include "parametricCurveDrawer.h"
00021 #include "parametricCurve.h"
00022 #include "config_parametrics.h"
00023 
00024 TypeHandle ParametricCurveDrawer::_type_handle;
00025 
00026 ////////////////////////////////////////////////////////////////////
00027 //     Function: ParametricCurveDrawer::Constructor
00028 //       Access: Published
00029 //  Description:
00030 ////////////////////////////////////////////////////////////////////
00031 ParametricCurveDrawer::
00032 ParametricCurveDrawer() {
00033   _lines.set_color(1.0f, 1.0f, 1.0f);
00034   _ticks.set_color(1.0f, 0.0f, 0.0f);
00035   _tick_scale = 0.1;
00036   _num_segs = 100.0;
00037   _num_ticks = 0.0f;
00038   _frame_accurate = false;
00039   _geom_node = new GeomNode("pcd");
00040   _drawn = false;
00041 }
00042 
00043 ////////////////////////////////////////////////////////////////////
00044 //     Function: ParametricCurveDrawer::Destructor
00045 //       Access: Published, Virtual
00046 //  Description:
00047 ////////////////////////////////////////////////////////////////////
00048 ParametricCurveDrawer::
00049 ~ParametricCurveDrawer() {
00050   hide();
00051 
00052   // Unregister all the curves.
00053   clear_curves();
00054 }
00055 
00056 
00057 ////////////////////////////////////////////////////////////////////
00058 //     Function: ParametricCurveDrawer::set_curve
00059 //       Access: Published
00060 //  Description: Sets the drawer up to draw just the one curve.
00061 ////////////////////////////////////////////////////////////////////
00062 void ParametricCurveDrawer::
00063 set_curve(ParametricCurve *curve) {
00064   PT(ParametricCurveCollection) curves = new ParametricCurveCollection();
00065   curves->add_curve(curve);
00066   set_curves(curves);
00067 }
00068 
00069 ////////////////////////////////////////////////////////////////////
00070 //     Function: ParametricCurveDrawer::set_curves
00071 //       Access: Published
00072 //  Description: Sets the drawer up to draw the curves in the
00073 //               indicated collection.  The drawer will actually draw
00074 //               just the first XYZ curve in the collection, but if
00075 //               one or more timewarps are present, this will affect
00076 //               the placement of tick marks.
00077 ////////////////////////////////////////////////////////////////////
00078 void ParametricCurveDrawer::
00079 set_curves(ParametricCurveCollection *curves) {
00080   if (curves != _curves) {
00081     // First, unregister the old curves.
00082     if (_curves != (ParametricCurveCollection *)NULL) {
00083       _curves->unregister_drawer(this);
00084     }
00085 
00086     _curves = curves;
00087 
00088     // Now, register the new ones.
00089     if (_curves != (ParametricCurveCollection *)NULL) {
00090       _curves->register_drawer(this);
00091     }
00092 
00093     redraw();
00094   }
00095 }
00096 
00097 ////////////////////////////////////////////////////////////////////
00098 //     Function: ParametricCurveDrawer::clear_curves
00099 //       Access: Published
00100 //  Description: Empties the list of curves the drawer will update.
00101 //               It will draw nothing.
00102 ////////////////////////////////////////////////////////////////////
00103 void ParametricCurveDrawer::
00104 clear_curves() {
00105   set_curves((ParametricCurveCollection *)NULL);
00106 }
00107 
00108 ////////////////////////////////////////////////////////////////////
00109 //     Function: ParametricCurveDrawer::get_curves
00110 //       Access: Published
00111 //  Description:
00112 ////////////////////////////////////////////////////////////////////
00113 ParametricCurveCollection *ParametricCurveDrawer::
00114 get_curves() {
00115   return _curves;
00116 }
00117 
00118 
00119 ////////////////////////////////////////////////////////////////////
00120 //     Function: ParametricCurveDrawer::get_geom_node
00121 //       Access: Published
00122 //  Description: Returns a pointer to the drawer's GeomNode.  This is
00123 //               where the drawer will build the visible
00124 //               representation of the curve.  This GeomNode must be
00125 //               inserted into the scene graph to make the curve
00126 //               visible.  The GeomNode remains connected to the drawer,
00127 //               so that future updates to the drawer will reflect in
00128 //               the GeomNode, and the GeomNode will be emptied when the
00129 //               drawer destructs.  Also see detach_geom_node().
00130 ////////////////////////////////////////////////////////////////////
00131 GeomNode *ParametricCurveDrawer::
00132 get_geom_node() {
00133   return _geom_node;
00134 }
00135 
00136 
00137 ////////////////////////////////////////////////////////////////////
00138 //     Function: ParametricCurveDrawer::detach_geom_node
00139 //       Access: Published
00140 //  Description: Detaches the GeomNode from the drawer so that the
00141 //               drawing will remain after the death of the drawer.
00142 //               Returns the now-static GeomNode.  A new, dynamic GeomNode
00143 //               is created for the drawer's future use; get_geom_node()
00144 //               will return this new GeomNode which will be empty until
00145 //               the next call to draw().
00146 ////////////////////////////////////////////////////////////////////
00147 PT(GeomNode) ParametricCurveDrawer::
00148 detach_geom_node() {
00149   if (!_drawn) {
00150     draw();
00151   }
00152   PT(GeomNode) g = _geom_node;
00153   _geom_node = new GeomNode("pcd");
00154   _drawn = false;
00155   return g;
00156 }
00157 
00158 
00159 ////////////////////////////////////////////////////////////////////
00160 //     Function: ParametricCurveDrawer::set_num_segs
00161 //       Access: Published
00162 //  Description: Specifies the number of line segments used to
00163 //               approximate the curve for each parametric unit.  This
00164 //               just affects the visual appearance of the curve as it
00165 //               is drawn.  The total number of segments drawn for the
00166 //               curve will be get_max_t() * get_num_segs().
00167 ////////////////////////////////////////////////////////////////////
00168 void ParametricCurveDrawer::
00169 set_num_segs(float num_segs) {
00170   _num_segs = num_segs;
00171   redraw();
00172 }
00173 
00174 ////////////////////////////////////////////////////////////////////
00175 //     Function: ParametricCurveDrawer::get_num_segs
00176 //       Access: Published
00177 //  Description: Returns the number of line segments used to
00178 //               approximate the curve for each parametric unit.  This
00179 //               just affects the visual appearance of the curve as it
00180 //               is drawn.  The total number of segments drawn for the
00181 //               curve will be get_max_t() * get_num_segs().
00182 ////////////////////////////////////////////////////////////////////
00183 float ParametricCurveDrawer::
00184 get_num_segs() const {
00185   return _num_segs;
00186 }
00187 
00188 
00189 ////////////////////////////////////////////////////////////////////
00190 //     Function: ParametricCurveDrawer::set_num_ticks
00191 //       Access: Published
00192 //  Description: Specifies the number of time tick marks drawn
00193 //               for each unit of time.  These tick marks are drawn at
00194 //               equal increments in time to give a visual
00195 //               approximation of speed.  Specify 0 to disable drawing
00196 //               of tick marks.
00197 ////////////////////////////////////////////////////////////////////
00198 void ParametricCurveDrawer::
00199 set_num_ticks(float num_ticks) {
00200   _num_ticks = num_ticks;
00201   redraw();
00202 }
00203 
00204 ////////////////////////////////////////////////////////////////////
00205 //     Function: ParametricCurveDrawer::get_num_ticks
00206 //       Access: Published
00207 //  Description: Returns the number of time tick marks per unit of
00208 //               time drawn.
00209 ////////////////////////////////////////////////////////////////////
00210 float ParametricCurveDrawer::
00211 get_num_ticks() const {
00212   return _num_ticks;
00213 }
00214 
00215 
00216 
00217 ////////////////////////////////////////////////////////////////////
00218 //     Function: ParametricCurveDrawer::set_color
00219 //       Access: Published
00220 //  Description: Specifies the color of the curve when it is drawn.
00221 //               The default is white.
00222 ////////////////////////////////////////////////////////////////////
00223 void ParametricCurveDrawer::
00224 set_color(float r, float g, float b) {
00225   _lines.set_color(r, g, b);
00226 }
00227 
00228 
00229 ////////////////////////////////////////////////////////////////////
00230 //     Function: ParametricCurveDrawer::set_color
00231 //       Access: Published
00232 //  Description: Specifies the color of the time tick marks drawn on
00233 //               the curve.  The default is red.
00234 ////////////////////////////////////////////////////////////////////
00235 void ParametricCurveDrawer::
00236 set_tick_color(float r, float g, float b) {
00237   _ticks.set_color(r, g, b);
00238 }
00239 
00240 
00241 ////////////////////////////////////////////////////////////////////
00242 //     Function: ParametricCurveDrawer::set_frame_accurate
00243 //       Access: Published
00244 //  Description: Specifies whether the curve drawn is to be
00245 //               frame-accurate.  If true, then changes made to the
00246 //               curve dynamically after it has been drawn will be
00247 //               reflected correctly in the render window.  If false,
00248 //               dynamic updates may be drawn before the rest of the
00249 //               scene has updated.
00250 ////////////////////////////////////////////////////////////////////
00251 void ParametricCurveDrawer::
00252 set_frame_accurate(bool frame_accurate) {
00253   _frame_accurate = frame_accurate;
00254   redraw();
00255 }
00256 
00257 ////////////////////////////////////////////////////////////////////
00258 //     Function: ParametricCurveDrawer::get_frame_accurate
00259 //       Access: Published
00260 //  Description: Returns whether the curve is drawn in frame-accurate
00261 //               mode.
00262 ////////////////////////////////////////////////////////////////////
00263 bool ParametricCurveDrawer::
00264 get_frame_accurate() const {
00265   return _frame_accurate;
00266 }
00267 
00268 
00269 
00270 ////////////////////////////////////////////////////////////////////
00271 //     Function: ParametricCurveDrawer::draw
00272 //       Access: Published, Virtual
00273 //  Description: Creates a series of line segments that approximates
00274 //               the curve.  These line segments may be made visible
00275 //               by parenting the node returned by get_geom_node()
00276 //               into the scene graph.
00277 ////////////////////////////////////////////////////////////////////
00278 bool ParametricCurveDrawer::
00279 draw() {
00280   // First, remove the old drawing, if any.
00281   hide();
00282 
00283   _drawn = true;
00284 
00285   // If there's no curve, draw nothing and return false.
00286   if (_curves == (ParametricCurveCollection *)NULL) {
00287     return false;
00288   }
00289 
00290   ParametricCurve *xyz_curve = _curves->get_default_curve();
00291   if (xyz_curve == (ParametricCurve *)NULL) {
00292     return false;
00293   }
00294 
00295   // Otherwise, let's go to town!
00296 
00297   // Make sure the curve(s) are fresh.
00298   _curves->recompute();
00299 
00300   int total_segs = (int)cfloor(_curves->get_max_t() * _num_segs + 0.5);
00301 
00302   float max_t = xyz_curve->get_max_t();
00303   float scale = max_t / (float)(total_segs-1);
00304   float t;
00305   LVecBase3f point;
00306   bool last_in, next_in;
00307 
00308   last_in = false;
00309   int i;
00310 
00311   for (i = 0; i < total_segs; i++) {
00312     t = (float)i * scale;
00313 
00314     next_in = xyz_curve->get_point(t, point);
00315 
00316     if (!next_in || !last_in) {
00317       _lines.move_to(point);
00318     } else {
00319       _lines.draw_to(point);
00320     }
00321     last_in = next_in;
00322   }
00323 
00324   _lines.create(_geom_node, _frame_accurate);
00325 
00326   max_t = get_max_t();
00327   scale = max_t / (float)(total_segs-1);
00328 
00329   // Now draw the time tick marks.
00330   if (_num_ticks > 0.0f) {
00331     int total_ticks = (int)cfloor(max_t * _num_ticks + 0.5);
00332     ParametricCurve *xyz_curve = _curves->get_default_curve();
00333     //    ParametricCurve *hpr_curve = _curves->get_hpr_curve();
00334 
00335     scale = max_t / (float)total_ticks;
00336 
00337     for (i = 0; i <= total_ticks; i++) {
00338       t = (float)i * scale;
00339       float t0 = _curves->evaluate_t(t);
00340       LVecBase3f tangent;
00341 
00342       if (xyz_curve->get_pt(t0, point, tangent)) {
00343         // Draw crosses.
00344         LVecBase3f t1, t2;
00345         get_tick_marks(tangent, t1, t2);
00346 
00347         _ticks.move_to(point - t1 * _tick_scale);
00348         _ticks.draw_to(point + t1 * _tick_scale);
00349         _ticks.move_to(point - t2 * _tick_scale);
00350         _ticks.draw_to(point + t2 * _tick_scale);
00351       }
00352     }
00353     _ticks.create(_geom_node, _frame_accurate);
00354   }
00355 
00356   return true;
00357 }
00358 
00359 
00360 
00361 
00362 ////////////////////////////////////////////////////////////////////
00363 //     Function: ParametricCurveDrawer::hide
00364 //       Access: Published
00365 //  Description: Removes the lines that were created by a previous
00366 //               call to draw().
00367 ////////////////////////////////////////////////////////////////////
00368 void ParametricCurveDrawer::
00369 hide() {
00370   _geom_node->remove_all_geoms();
00371   _drawn = false;
00372 }
00373 
00374 
00375 ////////////////////////////////////////////////////////////////////
00376 //     Function: ParametricCurveDrawer::set_tick_scale
00377 //       Access: Published
00378 //  Description: Sets the visible size of the time tick marks or
00379 //               geometry.
00380 ////////////////////////////////////////////////////////////////////
00381 void ParametricCurveDrawer::
00382 set_tick_scale(float scale) {
00383   _tick_scale = scale;
00384   redraw();
00385 }
00386 
00387 
00388 ////////////////////////////////////////////////////////////////////
00389 //     Function: ParametricCurveDrawer::get_tick_scale
00390 //       Access: Published
00391 //  Description: Returns the size of the time tick marks or geometry.
00392 ////////////////////////////////////////////////////////////////////
00393 float ParametricCurveDrawer::
00394 get_tick_scale() const {
00395   return _tick_scale;
00396 }
00397 
00398 ////////////////////////////////////////////////////////////////////
00399 //     Function: ParametricCurveDrawer::get_tick_marks
00400 //       Access: Private, Static
00401 //  Description: Given a tangent vector, computes two vectors at right
00402 //               angles to the tangent and to each other, suitable for
00403 //               drawing as tick marks.
00404 ////////////////////////////////////////////////////////////////////
00405 void ParametricCurveDrawer::
00406 get_tick_marks(const LVecBase3f &tangent, LVecBase3f &t1, LVecBase3f &t2) {
00407   LVector3f tn = tangent;
00408   tn.normalize();
00409 
00410   // Decide the smallest axis of tn and cross with the corresponding
00411   // unit vector.
00412   if (fabs(tn[0]) <= fabs(tn[1]) && fabs(tn[0]) <= fabs(tn[2])) {
00413     // X is smallest.
00414     t1 = tn.cross(LVector3f(1.0f, 0.0f, 0.0f));
00415 
00416   } else if (fabs(tn[1]) <= fabs(tn[2])) {
00417     // Y is smallest.
00418     t1 = tn.cross(LVector3f(0.0f, 1.0f, 0.0f));
00419 
00420   } else {
00421     // Z is smallest.
00422     t1 = tn.cross(LVector3f(0.0f, 0.0f, 1.0f));
00423   }
00424 
00425   t2 = tn.cross(t1);
00426 }

Generated on Fri May 2 00:40:50 2003 for Panda by doxygen1.3