Title: Mouse-Based Viewing
1Mouse-BasedViewing Navigation
- Glenn G. ChappellCHAPPELLG_at_member.ams.org
- U. of Alaska Fairbanks
- CS 381 Lecture Notes
- Monday, November 3, 2003
2ReviewAdvanced Viewing 1/4
- In most of the programs we have dealt with, we
have constructed the model/view transformation
from scratch each display cycle. - This becomes inconvenient when we implement some
of the more advanced viewing interfaces (driving,
flying, etc.). - In these interfaces we often want to add an
increasing number of transformations at the end
of the sequence ( beginning of the code). - Solution
- Save the viewing transformation in a (global)
variable. - When the transformation needs to be changed,
modify this variable. - Use the variable in the display function.
- Remember, the saved matrix should be treated like
other display-related globals in a GLUT program. - Cue music for flashback
3Blast from the PastBack in mid-September
- To add keypress-based display changes to a GLUT
program - A global variable is needed to hold the current
state of whatever part of the display is to
change. - Declare the variable.
- Initialize this variable to an appropriate value
somewhere. - In its declaration?
- In the init function?
- In the display function
- Use the value of this variable.
- Draw whatever should be drawn, according to the
current value of the variable. - Do not change the variable in the display
function. - In the keyboard function, when the appropriate
key is pressed - Change the value of the variable.
- Call glutPostRedisplay().
- Do not call the display function.
4ReviewAdvanced Viewing 2/4
- We handle matrix globals similarly to other GLUT
globals - Declare the variable.
- GLdouble your_matrix_variable16
- Initialize the variable.
- In the init function, often.
- Or maybe in a reset function, to be called
during initialization, and also when the user
does an Im lost keypress. - glMatrixMode(GL_MODELVIEW)
- glPushMatrix()
- Transformation commands go here?
- glGetDoublev(GL_MODELVIEW_MATRIX,
your_matrix_variable) - glPopMatrix()
5ReviewAdvanced Viewing 3/4
- In the display function
- Use the variable.
- glPushMatrix() // Do NOT forget the push-pop
pairs! - glTranslated(0., 0., -3.) // MAYBE this goes
here. - // MAYBE it goes in
init. - glMultMatrixd(your_matrix_variable)
- Draw something here
- glPopmatrix()
- More on that glTranslate command MAYBE stuff
in a bit.
6ReviewAdvanced Viewing 4/4
- Where appropriate (keyboard? special? mouse?
motion?) - Change the value of the variable.
- Call glutPostRedisplay().
- glPushMatrix()
- Transformation commands go here?
- glMultMatrixd(your_matrix_variable)
- glGetDoublev(GL_MODELVIEW_MATRIX,
your_matrix_variable) - glPopMatrix()
- glutPostRedisplay()
7More on Advanced ViewingTwo Kinds of Interfaces
- Now, about that translation
- In our zoom pan, driving, the translation
was done in the display function, not the saved
matrix. - But in flying the translation was in the saved
matrix. - Advanced interfaces can be divided into two
categories - View the world interfaces.
- We look at the scene.
- Rotation and scaling are centered on the point we
are looking at. - So the translation does not go in the saved
matrix. - Examples
- Driving from above.
- Object manipulation.
- Move in the world interfaces.
- In these, we are explicitly inside the scene.
- Rotation is centered on the camera.
- So the translation goes in the saved matrix.
- Examples
- Flying.
- Driving, where we appear to be inside the car.
8Mouse-Based ViewingOverview
- Today we will look at two mouse-based viewing
interfaces. - Click-and-drag rotation.
- View an object and rotate it in an intuitive way
with the mouse (click-and-drag). - Flying with the mouse.
- Fly forward on mouse-button press.
- Turn in the direction of the mouse position.
- Both of these will require the saved-matrix
techniques we looked at last time. - Sample code will not be given on the web page
yet. - However, hints and code snippets are in these
slides. Feel free to use them.
9Mouse-Based ViewingClick-and-Drag Rotation 1/3
- Interface Description
- We view an object, centered in the window.
- The object is normally motionless.
- When we click the left mouse button and drag, the
object rotates in a reasonable way. - When the mouse stops moving, or the mouse button
is released, the object stops moving. - Questions
- Is this view the world or move in the world?
- How do we determine what axis to rotate the
object about? - Does our new rotation come before or after the
old, in the code? - How much do we rotate the object?
10Mouse-Based ViewingClick-and-Drag Rotation 2/3
- My Answers
- Is this view the world or move in the world?
- This is view the world.
- Therefore, the big translation that moves the
object to where we can see it, should not be in
the saved matrix. - How do we determine what axis to rotate the
object about? - Rotate about an axis perpendicular to the recent
mouse motion. - The recent motion is the difference between the
last two mouse positions. - Does our new rotation come before or after the
old, in the code? - Before.
- Yes, we are rotating an object (which suggests
and answer of after). However, we are not
rotating in the objects own natural coordinate
system, but in the worlds. - How much do we rotate the object?
- Rotate the object by an amount proportional to
the length of the most recent mouse motion (the
distance between the last two positions). - Note
- There are other ways to design implement a
mouse-based object-manipulation interface. Try to
make a better one!
11Mouse-Based ViewingPerpendicular Rotation
- If we rotate (x, y) 90? counterclockwise, we get
(y, x). - Based on this idea, here is some useful code.
- // perprot
- // Rotates about an axis in the x,y-plane,
perpendicular to the given - // vector (vx, vy). Rotation amount is
proportional to the length of - // the vector and to rotmultiplier.
- void perprot(double rotmultiplier, double vx,
double vy) -
- double len sqrt(vxvx vyvy)
- glPushMatrix()
- glRotated(rotmultiplierlen, -vy,vx,0.)
- glMultMatrixd(your_matrix_variable)
- glGetDoublev(GL_MODELVIEW_MATRIX,
your_matrix_variable) - glPopMatrix()
- glutPostRedisplay()
12Mouse-Based ViewingClick-and-Drag Rotation 3/3
- A few thoughts about implementing this interface
- GLUT and OpenGL handle y-coordinates differently.
- Save the window dimensions in the reshape
function. Then subtract GLUTs mouse y to get a
number useful to OpenGL. - Save the mouse position whenever the left button
is down. - Are we saving it in GLUT or OpenGL format? Be
consistent! - Remember mouse motion are called for other
buttons, too. - Save the state of the left button in the mouse
function. - Test this state in the motion function.
- If the left button is up, do not alter the scene.
- That said, all that is left is for motion to call
perprot with the difference between the current
and previous mouse positions. - Change rotfactor to speed up or slow down the
rotation. - Now write it!
13Mouse-Based ViewingFlying with the Mouse 1/3
- Interface Description
- We are inside the scene, moving and turning.
- If the mouse is centered in the window, we do not
rotate. - Otherwise, we rotate toward the mouse point.
- If the left mouse button is down, we fly forward.
- Otherwise, we are stationary (although we may be
rotating). - Questions
- Is this view the world or move in the world?
- How do we determine what axis to rotate about?
- Does our new rotation come before or after the
old, in the code? - How much do we rotate?
14Mouse-Based ViewingFlying with the Mouse 2/3
- My Answers
- Is this view the world or move in the world?
- This is move in the world.
- Therefore, the big translation should be in the
saved matrix. - How do we determine what axis to rotate about?
- Rotate about an axis perpendicular to the
difference between the mouse position and the
center of the window. - Does our new rotation come before or after the
old, in the code? - Before. (This is easier to figure out, right?)
- How much do we rotate?
- Rotate the object by an amount proportional to
the distance between the mouse position and the
center of the window. - So, again, we have a vector. We rotate about an
axis perpendicular to it, by an amount
proportional to its length. It looks like we can
use perprot again. - We probably need to change rotfactor.
- Note
- Again, can you do better?
15Mouse-Based ViewingFlying with the Mouse 3/3
- A few thoughts about implementing this interface
- We want to rotate when the mouse button is not
pressed. - So we need to use the passive motion function.
- We want the scene to change when the mouse is not
moving. - So the scene changing should go in the idle
function. - This means that all the mouse, motion, and
passive motion functions need to do is to save
the button state and mouse position. - Idle does the rest.
- We still need the window dimensions from reshape,
in order to find the center of the window. - Now write it!
- Another thought we need a roll function.
Otherwise, we end up flying sideways much of the
time.
16Mouse-Based ViewingAnother Flying Interface
- In class I implemented what I call a
spaceship-style flying interface. - In such an interface, there is no meaningful up
direction. - You can fly in any direction orientation you
want. ? - It is very easy to get lost or disoriented. ?
- Another alternative is an airplane-style
interface. - Here, there is a well-defined up direction.
- Turning left and right would rotate about the
worlds up-vector, not the cameras. - I guess is there a better way?
- To think about
- How would an airplane-style flying interface be
implemented?