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

panda/src/tform/trackball.cxx

Go to the documentation of this file.
00001 // Filename: trackball.cxx
00002 // Created by:  drose (12Mar02)
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 #include "trackball.h"
00020 #include "buttonEvent.h"
00021 #include "buttonEventList.h"
00022 #include "dataNodeTransmit.h"
00023 #include "compose_matrix.h"
00024 #include "mouseData.h"
00025 #include "modifierButtons.h"
00026 
00027 TypeHandle Trackball::_type_handle;
00028 
00029 // These are used internally.
00030 #define B1_MASK 0x1
00031 #define B2_MASK 0x2
00032 #define B3_MASK 0x4
00033 
00034 ////////////////////////////////////////////////////////////////////
00035 //     Function: Trackball::Constructor
00036 //       Access: Public
00037 //  Description:
00038 ////////////////////////////////////////////////////////////////////
00039 Trackball::
00040 Trackball(const string &name) :
00041   DataNode(name)
00042 {
00043   _pixel_xy_input = define_input("pixel_xy", EventStoreVec2::get_class_type());
00044   _button_events_input = define_input("button_events", ButtonEventList::get_class_type());
00045 
00046   _transform_output = define_output("transform", EventStoreTransform::get_class_type());
00047 
00048   _transform = new EventStoreTransform(TransformState::make_identity());
00049 
00050   _rotscale = 0.3f;
00051   _fwdscale = 0.3f;
00052 
00053   _lastx = _lasty = 0.5f;
00054 
00055   _rotation = LMatrix4f::ident_mat();
00056   _translation.set(0.0f, 0.0f, 0.0f);
00057   _mat = LMatrix4f::ident_mat();
00058   _orig = LMatrix4f::ident_mat();
00059   _invert = true;
00060   _cs = default_coordinate_system;
00061 
00062   _mods.add_button(MouseButton::one());
00063   _mods.add_button(MouseButton::two());
00064   _mods.add_button(MouseButton::three());
00065 }
00066 
00067 ////////////////////////////////////////////////////////////////////
00068 //     Function: Trackball::Destructor
00069 //       Access: Published
00070 //  Description:
00071 ////////////////////////////////////////////////////////////////////
00072 Trackball::
00073 ~Trackball() {
00074 }
00075 
00076 ////////////////////////////////////////////////////////////////////
00077 //     Function: Trackball::reset
00078 //       Access: Published
00079 //  Description: Reinitializes all transforms to identity.
00080 ////////////////////////////////////////////////////////////////////
00081 void Trackball::
00082 reset() {
00083   _rotation = LMatrix4f::ident_mat();
00084   _translation.set(0.0f, 0.0f, 0.0f);
00085   _orig = LMatrix4f::ident_mat();
00086   _mat = LMatrix4f::ident_mat();
00087 }
00088 
00089 ////////////////////////////////////////////////////////////////////
00090 //     Function: Trackball::get_forward_scale
00091 //       Access: Published
00092 //  Description: Returns the scale factor applied to forward and
00093 //               backward motion.  See set_forward_scale().
00094 ////////////////////////////////////////////////////////////////////
00095 float Trackball::
00096 get_forward_scale() const {
00097   return _fwdscale;
00098 }
00099 
00100 ////////////////////////////////////////////////////////////////////
00101 //     Function: Trackball::set_forward_scale
00102 //       Access: Published
00103 //  Description: Changes the scale factor applied to forward and
00104 //               backward motion.  The larger this number, the faster
00105 //               the model will move in response to dollying in and
00106 //               out.
00107 ////////////////////////////////////////////////////////////////////
00108 void Trackball::
00109 set_forward_scale(float fwdscale) {
00110   _fwdscale = fwdscale;
00111 }
00112 
00113 
00114 ////////////////////////////////////////////////////////////////////
00115 //     Function: Trackball::get_pos
00116 //       Access: Published
00117 //  Description: Return the offset from the center of rotation.
00118 ////////////////////////////////////////////////////////////////////
00119 const LPoint3f &Trackball::
00120 get_pos() const {
00121   return _translation;
00122 }
00123 
00124 float Trackball::
00125 get_x() const {
00126   return _translation[0];
00127 }
00128 
00129 float Trackball::
00130 get_y() const {
00131   return _translation[1];
00132 }
00133 
00134 float Trackball::
00135 get_z() const {
00136   return _translation[2];
00137 }
00138 
00139 
00140 ////////////////////////////////////////////////////////////////////
00141 //     Function: Trackball::set_pos
00142 //       Access: Published
00143 //  Description: Directly set the offset from the rotational origin.
00144 ////////////////////////////////////////////////////////////////////
00145 void Trackball::
00146 set_pos(const LVecBase3f &vec) {
00147   _translation = vec;
00148   recompute();
00149 }
00150 
00151 void Trackball::
00152 set_pos(float x, float y, float z) {
00153   _translation.set(x, y, z);
00154   recompute();
00155 }
00156 
00157 void Trackball::
00158 set_x(float x) {
00159   _translation[0] = x;
00160   recompute();
00161 }
00162 
00163 void Trackball::
00164 set_y(float y) {
00165   _translation[1] = y;
00166   recompute();
00167 }
00168 
00169 void Trackball::
00170 set_z(float z) {
00171   _translation[2] = z;
00172   recompute();
00173 }
00174 
00175 
00176 ////////////////////////////////////////////////////////////////////
00177 //     Function: Trackball::get_hpr
00178 //       Access: Published
00179 //  Description: Return the trackball's orientation.
00180 ////////////////////////////////////////////////////////////////////
00181 LVecBase3f Trackball::
00182 get_hpr() const {
00183   LVecBase3f scale, hpr, translate;
00184   decompose_matrix(_rotation, scale, hpr, translate);
00185   return hpr;
00186 }
00187 
00188 float Trackball::
00189 get_h() const {
00190   LVecBase3f scale, hpr, translate;
00191   decompose_matrix(_rotation, scale, hpr, translate);
00192   return hpr[0];
00193 }
00194 
00195 float Trackball::
00196 get_p() const {
00197   LVecBase3f scale, hpr, translate;
00198   decompose_matrix(_rotation, scale, hpr, translate);
00199   return hpr[1];
00200 }
00201 
00202 float Trackball::
00203 get_r() const {
00204   LVecBase3f scale, hpr, translate;
00205   decompose_matrix(_rotation, scale, hpr, translate);
00206   return hpr[2];
00207 }
00208 
00209 
00210 ////////////////////////////////////////////////////////////////////
00211 //     Function: Trackball::set_hpr
00212 //       Access: Published
00213 //  Description: Directly set the mover's orientation.
00214 ////////////////////////////////////////////////////////////////////
00215 void Trackball::
00216 set_hpr(const LVecBase3f &hpr) {
00217   LVecBase3f scale, old_hpr, translate;
00218   decompose_matrix(_rotation, scale, old_hpr, translate);
00219   compose_matrix(_rotation, scale, hpr, translate);
00220   recompute();
00221 }
00222 
00223 void Trackball::
00224 set_hpr(float h, float p, float r) {
00225   LVecBase3f scale, hpr, translate;
00226   decompose_matrix(_rotation, scale, hpr, translate);
00227   hpr.set(h, p, r);
00228   compose_matrix(_rotation, scale, hpr, translate);
00229   recompute();
00230 }
00231 
00232 void Trackball::
00233 set_h(float h) {
00234   LVecBase3f scale, hpr, translate;
00235   decompose_matrix(_rotation, scale, hpr, translate);
00236   hpr[0] = h;
00237   compose_matrix(_rotation, scale, hpr, translate);
00238   recompute();
00239 }
00240 
00241 void Trackball::
00242 set_p(float p) {
00243   LVecBase3f scale, hpr, translate;
00244   decompose_matrix(_rotation, scale, hpr, translate);
00245   hpr[1] = p;
00246   compose_matrix(_rotation, scale, hpr, translate);
00247   recompute();
00248 }
00249 
00250 void Trackball::
00251 set_r(float r) {
00252   LVecBase3f scale, hpr, translate;
00253   decompose_matrix(_rotation, scale, hpr, translate);
00254   hpr[2] = r;
00255   compose_matrix(_rotation, scale, hpr, translate);
00256   recompute();
00257 }
00258 
00259 
00260 ////////////////////////////////////////////////////////////////////
00261 //     Function: Trackball::reset_origin_here
00262 //       Access: Published
00263 //  Description: Reposition the center of rotation to coincide with
00264 //               the current translation offset.  Future rotations
00265 //               will be about the current origin.
00266 ////////////////////////////////////////////////////////////////////
00267 void Trackball::
00268 reset_origin_here() {
00269   recompute();
00270   _rotation = _orig;
00271   _translation.set(0.0f, 0.0f, 0.0f);
00272 }
00273 
00274 
00275 ////////////////////////////////////////////////////////////////////
00276 //     Function: Trackball::move_origin
00277 //       Access: Published
00278 //  Description: Moves the center of rotation by the given amount.
00279 ////////////////////////////////////////////////////////////////////
00280 void Trackball::
00281 move_origin(float x, float y, float z) {
00282   _rotation = LMatrix4f::translate_mat(LVecBase3f(x, y, z)) *  _rotation;
00283 }
00284 
00285 ////////////////////////////////////////////////////////////////////
00286 //     Function: Trackball::get_origin
00287 //       Access: Published
00288 //  Description: Returns the current center of rotation.
00289 ////////////////////////////////////////////////////////////////////
00290 LPoint3f Trackball::
00291 get_origin() const {
00292   return _rotation.get_row3(3);
00293 }
00294 
00295 ////////////////////////////////////////////////////////////////////
00296 //     Function: Trackball::set_origin
00297 //       Access: Published
00298 //  Description: Directly sets the center of rotation.
00299 ////////////////////////////////////////////////////////////////////
00300 void Trackball::
00301 set_origin(const LVecBase3f &origin) {
00302   _rotation.set_row(3, LVecBase3f(0.0f, 0.0f, 0.0f));
00303   _rotation = LMatrix4f::translate_mat(-origin) *  _rotation;
00304 }
00305 
00306 
00307 ////////////////////////////////////////////////////////////////////
00308 //     Function: Trackball::set_invert
00309 //       Access: Published
00310 //  Description: Sets the invert flag.  When this is set, the inverse
00311 //               matrix is generated, suitable for joining to a
00312 //               camera, instead of parenting the scene under it.
00313 ////////////////////////////////////////////////////////////////////
00314 void Trackball::
00315 set_invert(bool flag) {
00316   _invert = flag;
00317 }
00318 
00319 ////////////////////////////////////////////////////////////////////
00320 //     Function: Trackball::get_invert
00321 //       Access: Published
00322 //  Description: Returns the invert flag.  When this is set, the
00323 //               inverse matrix is generated, suitable for joining to
00324 //               a camera, instead of parenting the scene under it.
00325 ////////////////////////////////////////////////////////////////////
00326 bool Trackball::
00327 get_invert() const {
00328   return _invert;
00329 }
00330 
00331 ////////////////////////////////////////////////////////////////////
00332 //     Function: Trackball::set_rel_to
00333 //       Access: Published
00334 //  Description: Sets the NodePath that all trackball manipulations
00335 //               are to be assumed to be relative to.  For instance,
00336 //               set your camera node here to make the trackball
00337 //               motion camera relative.  The default is the empty
00338 //               path, which means trackball motion is in global
00339 //               space.
00340 ////////////////////////////////////////////////////////////////////
00341 void Trackball::
00342 set_rel_to(const NodePath &rel_to) {
00343   _rel_to = rel_to;
00344 }
00345 
00346 ////////////////////////////////////////////////////////////////////
00347 //     Function: Trackball::get_rel_to
00348 //       Access: Published
00349 //  Description: Returns the NodePath that all trackball manipulations
00350 //               are relative to, or the empty path.
00351 ////////////////////////////////////////////////////////////////////
00352 const NodePath &Trackball::
00353 get_rel_to() const {
00354   return _rel_to;
00355 }
00356 
00357 
00358 ////////////////////////////////////////////////////////////////////
00359 //     Function: Trackball::set_coordinate_system
00360 //       Access: Published
00361 //  Description: Sets the coordinate system of the Trackball.
00362 //               Normally, this is the default coordinate system.
00363 //               This changes the axes the Trackball manipulates so
00364 //               that the user interface remains consistent across
00365 //               different coordinate systems.
00366 ////////////////////////////////////////////////////////////////////
00367 void Trackball::
00368 set_coordinate_system(CoordinateSystem cs) {
00369   _cs = cs;
00370 }
00371 
00372 ////////////////////////////////////////////////////////////////////
00373 //     Function: Trackball::get_coordinate_system
00374 //       Access: Published
00375 //  Description: Returns the coordinate system of the Trackball.
00376 //               See set_coordinate_system().
00377 ////////////////////////////////////////////////////////////////////
00378 CoordinateSystem Trackball::
00379 get_coordinate_system() const {
00380   return _cs;
00381 }
00382 
00383 ////////////////////////////////////////////////////////////////////
00384 //     Function: Trackball::set_mat
00385 //       Access: Published
00386 //  Description: Stores the indicated transform in the trackball.
00387 //               This is a transform in global space, regardless of
00388 //               the rel_to node.
00389 ////////////////////////////////////////////////////////////////////
00390 void Trackball::
00391 set_mat(const LMatrix4f &mat) {
00392   _orig = mat;
00393   if (_invert) {
00394     _mat = invert(_orig);
00395   } else {
00396     _mat = _orig;
00397   }
00398 
00399   reextract();
00400 }
00401 
00402 
00403 ////////////////////////////////////////////////////////////////////
00404 //     Function: Trackball::get_mat
00405 //       Access: Published
00406 //  Description: Returns the matrix represented by the trackball
00407 //               rotation.
00408 ////////////////////////////////////////////////////////////////////
00409 const LMatrix4f &Trackball::
00410 get_mat() const {
00411   return _orig;
00412 }
00413 
00414 ////////////////////////////////////////////////////////////////////
00415 //     Function: Trackball::get_trans_mat
00416 //       Access: Published
00417 //  Description: Returns the actual transform that will be applied to
00418 //               the scene graph.  This is the same as get_mat(),
00419 //               unless invert is in effect.
00420 ////////////////////////////////////////////////////////////////////
00421 const LMatrix4f &Trackball::
00422 get_trans_mat() const {
00423   return _mat;
00424 }
00425 
00426 
00427 ////////////////////////////////////////////////////////////////////
00428 //     Function: Trackball::apply
00429 //       Access: Private
00430 //  Description: Applies the operation indicated by the user's mouse
00431 //               motion to the current state.  Returns the matrix
00432 //               indicating the new state.
00433 ////////////////////////////////////////////////////////////////////
00434 void Trackball::
00435 apply(double x, double y, int button) {
00436   if (button && !_rel_to.is_empty()) {
00437     // If we have a rel_to node, we must first adjust our rotation and
00438     // translation to be in those local coordinates.
00439     reextract();
00440   }
00441   if (button == B1_MASK) {
00442     // Button 1: translate in plane parallel to screen.
00443 
00444     _translation +=
00445       x * _fwdscale * LVector3f::right(_cs) +
00446       y * _fwdscale * LVector3f::down(_cs);
00447 
00448   } else if (button == (B2_MASK | B3_MASK)) {
00449     // Buttons 2 + 3: rotate about the vector perpendicular to the
00450     // screen.
00451 
00452     _rotation *=
00453       LMatrix4f::rotate_mat_normaxis((x - y) * _rotscale,
00454                             LVector3f::forward(_cs), _cs);
00455 
00456   } else if ((button == B2_MASK) || (button == (B1_MASK | B3_MASK))) {
00457     // Button 2, or buttons 1 + 3: rotate about the right and up
00458     // vectors.  (We alternately define this as buttons 1 + 3, to
00459     // support two-button mice.)
00460 
00461     _rotation *=
00462       LMatrix4f::rotate_mat_normaxis(x * _rotscale, LVector3f::up(_cs), _cs) *
00463       LMatrix4f::rotate_mat_normaxis(y * _rotscale, LVector3f::right(_cs), _cs);
00464 
00465   } else if ((button == B3_MASK) || (button == (B1_MASK | B2_MASK))) {
00466     // Button 3, or buttons 1 + 2: dolly in and out along the forward
00467     // vector.  (We alternately define this as buttons 1 + 2, to
00468     // support two-button mice.)
00469     _translation -= y * _fwdscale * LVector3f::forward(_cs);
00470   }
00471 
00472   if (button) {
00473     recompute();
00474   }
00475 }
00476 
00477 
00478 ////////////////////////////////////////////////////////////////////
00479 //     Function: Trackball::reextract
00480 //       Access: Private
00481 //  Description: Given a correctly computed _orig matrix, rederive the
00482 //               translation and rotation elements.
00483 ////////////////////////////////////////////////////////////////////
00484 void Trackball::
00485 reextract() {
00486   LMatrix4f m = _orig;
00487   if (!_rel_to.is_empty()) {
00488     NodePath root;
00489     const LMatrix4f &rel_mat = root.get_mat(_rel_to);
00490     m = _orig * rel_mat;
00491   }
00492 
00493   m.get_row3(_translation,3);
00494   _rotation = m;
00495   _rotation.set_row(3, LVecBase3f(0.0f, 0.0f, 0.0f));
00496 }
00497 
00498 ////////////////////////////////////////////////////////////////////
00499 //     Function: Trackball::recompute
00500 //       Access: Private
00501 //  Description: Rebuilds the matrix according to the stored rotation
00502 //               and translation components.
00503 ////////////////////////////////////////////////////////////////////
00504 void Trackball::
00505 recompute() {
00506   _orig = _rotation * LMatrix4f::translate_mat(_translation);
00507 
00508   if (!_rel_to.is_empty()) {
00509     NodePath root;
00510     const LMatrix4f &rel_mat = _rel_to.get_mat(root);
00511     _orig = _orig * rel_mat;
00512   }
00513 
00514   if (_invert) {
00515     _mat = invert(_orig);
00516   } else {
00517     _mat = _orig;
00518   }
00519 }
00520 
00521 
00522 ////////////////////////////////////////////////////////////////////
00523 //     Function: Trackball::do_transmit_data
00524 //       Access: Protected, Virtual
00525 //  Description: The virtual implementation of transmit_data().  This
00526 //               function receives an array of input parameters and
00527 //               should generate an array of output parameters.  The
00528 //               input parameters may be accessed with the index
00529 //               numbers returned by the define_input() calls that
00530 //               were made earlier (presumably in the constructor);
00531 //               likewise, the output parameters should be set with
00532 //               the index numbers returned by the define_output()
00533 //               calls.
00534 ////////////////////////////////////////////////////////////////////
00535 void Trackball::
00536 do_transmit_data(const DataNodeTransmit &input, DataNodeTransmit &output) {
00537   // First, update our modifier buttons.
00538   if (input.has_data(_button_events_input)) {
00539     const ButtonEventList *button_events;
00540     DCAST_INTO_V(button_events, input.get_data(_button_events_input).get_ptr());
00541     button_events->update_mods(_mods);
00542   }
00543 
00544   // Now, check for mouse motion.
00545   if (input.has_data(_pixel_xy_input)) {
00546     const EventStoreVec2 *pixel_xy;
00547     DCAST_INTO_V(pixel_xy, input.get_data(_pixel_xy_input).get_ptr());
00548     const LVecBase2f &p = pixel_xy->get_value();
00549     float this_x = p[0];
00550     float this_y = p[1];
00551     int this_button = 0;
00552 
00553     if (_mods.is_down(MouseButton::one())) {
00554       this_button |= B1_MASK;
00555     }
00556     if (_mods.is_down(MouseButton::two())) {
00557       this_button |= B2_MASK;
00558     }
00559     if (_mods.is_down(MouseButton::three())) {
00560       this_button |= B3_MASK;
00561     }
00562 
00563     float x = this_x - _lastx;
00564     float y = this_y - _lasty;
00565 
00566     apply(x, y, this_button);
00567 
00568     _lastx = this_x;
00569     _lasty = this_y;
00570   }
00571 
00572   // Now send our matrix down the pipe.
00573   _transform->set_value(TransformState::make_mat(_mat));
00574   output.set_data(_transform_output, EventParameter(_transform));
00575 }

Generated on Fri May 2 00:44:30 2003 for Panda by doxygen1.3