A major challenge of the Robot project is designing a simple and intuitive user interface. The user should be able to control the camera as well as many different parts of the robot. In this tutorial/lab you'll create a simple camera control for your project and design (on paper) the robot controls.
To start, download the starting code here. Create a new visual studio project then build and run the executable. The program draws a set of coordinate axis centered at the origin. You should not be able to see them. By default, the viewpoint (peak of the frustum) is at the origin, looking down the negative z axis, with up in the positive y direction. If you check out the gluPerspective command in the init function, you'll see the near plane is one unit from the peak of the frustum. Nothing outside the frustum is seen, so in our current configuration the coordinate axis do not appear.
The glu library provides a variety of utility functions that are useful in OpenGL applications. One is gluLookAt(eyex, eyey, eyez, centx,centy,centz, upx, upy,ypz),
which, in effect, changes the viewpoint to be situated at (eyex,eyey,eyez), looking toward (centx, centy, centz) with up in the
< upx, upy, upz > direction.
Immediately after the load identity command in the display function add the following:
gluLookAt(0,0,2,0,0,0,0,1,0);Recompile and run the project. You should now see the x and y coordinate axes; you probably don't see the z axis because it is pointed directly at the camera. The gluLookAt command does not actually change the viewpoint because, in fact, OpenGL only supports the default viewpoint. Rather it transforms the world so that the desired viewpoint coincides with the default. In our case it translates the world -2 in the z direction. To confirm this, add the following after the gluLookAt command:
float m[16];
glGetFloatv(GL_MODELVIEW_MATRIX,m);
for (int i=0;i<4;i++) {
for (int j=0;j<4;j++)
cout << m[i*4+j];
cout << endl;
}
The glGetFloatv(GL_MODELVIEW,m) command puts the current contents of the modelview matrix in m. (Note the matrix is stored in
column-order.) The result is exactly the transform for translate by -2 in the z direction.
Change the viewpoint with the following command and you should now see all three coordinate axes.
gluLookAt(0,.2,2,0,0,0,0,1,0)
The gluLookAt command is very useful but it is important to remember that it should be called at the start of display immediately after the identity is loaded into the modelview matrix. You should not (except in exceptional circumstances we'll see later) reload the identity; instead use push and pop to render your scene graph.
Your next task is to allow the user to change the viewpoint using the mouse. First, we'll let the user rotate the camera about the origin. The mouse movement will determine the angles θ and φ in the following figure.
Left and right movement of the mouse should control the angle φ while up and down movements shouold contol θ. You need to decide how to convert mouse movement into changes in these angles and implement your scheme in the method motion(), which is the callback for glutMotionFunc(). Note: You only need to complete a few lines of code but you probably will need to tune them so that the control feels natural. Also, in order to prevent the view vector (from the viewpoint to the center of attention) from coinciding with our up vector, we constrain θ to be between -85 and 85 degrees.
Note the use of "glutPostRedisplay" in the motion function. Read up on this in the glut specs.
Incorporate your camera code into your last lab so that you can view your floor/sphere from any directions. Is there anything strange about the lights? Can you fix the problem?