Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

A virtual trackball rotation controller

0.00/5 (No votes)
1 Dec 1999 1  
  • Download source files - 16 Kb
  • Intro

    This piece of code was born inside an (unfinished) project of mine: a graphical curve editor with a real time 3D preview using OpenGL libraries.

    At first to let the user see the object being constructed from different points of view in the 3D window I simply linked mouse movement with rotation about two axes (usually X and Y when the camera is along Z).

    This method become unsatisfactory after a brief period of use cause it presented an odd effect when the object was "upside-down": moving the mouse to the right caused an apparent left rotation and vice-versa.

    The oddity was caused by the fact that the rotation has to be referred to the local object coordinate system, in the latter example the object is actually turning right while being upside-down.

    In computer graphics literature there are several papers about "intuitive" rotation controllers; I think K. Shoemake's arcball controller represents one of the best solutions: the idea is to project mouse movement on an hypothetical sphere filling the 3D window and to apply the rotation resulting from the sphere being manipulated when the mouse button is pressed to the object.

    Internals

    The global rotation is internally represented and adjusted by using quaternions instead of rotation matrices since this approach is more numerically stable when dealing with small, incremental rotations.

    This trackball is a features merging among the original arcball C code (rewritten in OO style) and a virtual trackball controller by J.Childs (used in his GLcube project) which is in turn derived from some code in M.J.Kilgard's GLUT library.

    The two code presented several similarities (such as the use of quaternions) but different sphere projection algorithms therefore I decided to retain both: J.Childs' controller project mouse movement on a parabolic sheet when it is outside the sphere while K.Shoemake's one project mouse movement on a plane; the first method (the default one) is somewhat more natural because it's effect is continuous while the second one is abruptly interrupted when the mouse leave/enters the virtual sphere.

    In the code I've (re)used a set of math classes which are part of my frequently used graphics programming tools, it's well commented and contains some documentation which can be extracted using Doxygen.

    Use

    The trackball code is demonstrated in the companion article CGLEnabledView - An MDI view class supporting OpenGL

    To use a CBallController in your programs follow these steps:

    1. Include BallController.h where needed.
    2. Construct a CBallController somewhere in your application (I suggest the view class) and specify at construction time the radius of the virtual sphere varying from 0.1 to 1.0 (a radius of 1.0 means that the sphere completely fills the window).
    3. [optional] Call SetAlternateMethod or ToggleMethod member functions to set a project-to-sphere method.
    4. Call the ClientAreaResize method in your window resize handler routine (which should be called before showing the window for the first time too) passing the size of your client area.
    5. [optional but recommended] Call the Key method passing the character code in your key press handler to enable manipulation trough keyboard (see below for the key bindings).
    6. [optional] Set the constraint axes via the UseConstraints method, constraints drawing can be controlled via SetDrawConstraints method.
    7. Call the MouseDown, MouseMove and MouseMove methods in your mouse handlers routines passing the mouse coordinates represented in local window coordinates (origin in upper left corner); it may be a good idea to capture mouse movements outside the windows during mouse button dragging.
    8. Call the IssueGLrotation method just before (re)drawing the scene.
    9. [optional] Call the DrawBall method after drawing the scene to let the BallController show some feedback during rotations using the alternate method.

    Other methods
    With GetDrawConstraints and you can check if constraint drawing is activated. GetAngleKeyIncrement and SetAngleKeyIncrement allow to respectively retrieve and set the angle increment used in keyboard interactions. GetColorV, GetColor, SetColor and SetColorV specify or retrieve the color used in DrawBall method, the color can be passed using a COLORREF structure or a vector of [0-1] ranging floats.
    Keys

    EscInterrupts current rotation operation (a rotation operation starts at every mouse button press)
    Canc or Numpad 5Resets the current rotation (corresponds to an identity rotation matrix)
    Right arrow or Numpad 6rotates +keyIncrement degrees about X axis
    Left arrow or Numpad 4rotates -keyIncrement degrees about X axis
    Up arrow or Numpad 8rotates +keyIncrement degrees about Y axis
    Down arrow or Numpad 2rotates -keyIncrement degrees about Y axis
    Page Up or Numpad 9rotates +keyIncrement degrees about Z axis
    Home or Numpad 7rotates -keyIncrement degrees about Z axis
    TABduring a constrained rotation swicth the constrain axis

    History

    Revision Description
    0.2 Initial public release
    0.1 Personal development release

    License

    This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

    A list of licenses authors might use can be found here