This document describes how to install and utilize the CGrCamera class. Many of you may have seen the way I can use the mouse to flip objects easily. This is the class that makes this possible.
It is assumed you have an OpenGL project that can display something. I tested this code with a simple cube example. If you need some code to use as an example, I've included it as the end of this page.
First off, you will need to get the files GrCamera.h, and GrCamera.cpp and install them into your project. I have put these and other files in graphics.zip. I suggest leaving these files in a subdirectory in your project called graphics. Then, select: Project/Add existing item. You can select one file at a time using this procedure or you can use the control key to select the new files and add them all at the same time. When you are done you should see CGrCamera as a class in Class View and your program should compile and run, albeit with no changes, yet.
We'll need a CGrCamera member variable in CChildView for our camera. Add this include statement to ChildView.h:
#include "graphics/GrCamera.h"
Then, add the following member variable to CChildView:
CGrCamera m_camera;
Add the following code to CChildView's constructor:
m_camera.Set(20, 10, 50, 0, 0, 0, 0, 1, 0);
m_camera.MouseMode(CGrCamera::PITCHYAW);
The parameters for Set should be whatever your current parameters for gluLookAt() are. They may be different from those here. The second line sets the mouse to control pitch and yaw on the image.
Next, replace your existing gluLookAt() call with this:
m_camera.gluLookAt();
There are no parameters. This calls gluLookAt with the current camera parameters. You should be able to compile and run this and everything will work that same way.
| If you are creating a new application, there is sample code at the end of this tutorial you can use to get the camera features up and going quickly. |
Now, let's activate the mouse. Click on CChildView in ClassView. There should be a "Properties" window on your screen. If you don't see one, right-click on CChildView and select the Properties option in the menu. In the Properties window, press the Messages button. This is the button that looks like a window with a lightning bolt in it:

You can move the mouse over each window to see the tool-tip. When you press this button you will see a list of WM_ messages. Click on WM_LBUTTONDOWN. To the right of the option, there will be a down-arrow. Click that and select <Add> OnLButtonDown to add a handler for left mouse button down messages. Do the same for WM_MOUSEMOVE.
For the body of CChildView::OnLButtonDown, use the following:
m_camera.MouseDown(point.x, point.y);
COpenGLWnd ::OnLButtonDown(nFlags, point);
For the body of CChildView::OnMouseMove, use the following:
if(nFlags & MK_LBUTTON)
{
m_camera.MouseMove(point.x, point.y);
Invalidate();
}
COpenGLWnd ::OnMouseMove(nFlags, point);
When you compile and run this, you should have mouse control of pitch and yaw.
There are several options you can control with the mouse. By setting a different mouse mode, you can control the camera pan and tilt and move and roll. You can also enable or disable gravity. Gravity forces the up direction to always be up. Suppose I want to add a menu option to select Pan/Tilt:
Go the resource view of the program menu (remember, we did this process in Step 1) and add a new menu called Camera. In that menu add an option called Pan/Tilt. Right click on the menu option in the resource (menu) editor. Choose Add Event Handler.. from this menu. This brings up the message handler dialog box. The message we will handle is COMMAND, the message sent when the menu option is selected. We want it handled by CChildView, so select that class from the class list. Press the Add and Edit button. In the body of the OnCameraPantilt function, put:
m_camera.MouseMode(CGrCamera::PANTILT);
Now, repeat the process for Pan/Tilt menu option, but this time add a handler for UPDATE_COMMAND_UI. In the body of CChildView::OnUpdateCameraPantilt, put:
pCmdUI->SetCheck(m_camera.MouseMode() == CGrCamera::PANTILT);
You'll probably want to add a menu option so you can reselect pitch/yaw as well. The current camera mouse mode options are:
CGrCamera::PANTILT, CGrCamera::ROLLMOVE, CGrCamera::PITCHYAW, CGrCamera::DOLLYXY
In addition, there is a function Gravity(bool p_gravity), which you can call with a boolean to set the gravity mode. An access function Gravity() is also available to get the current gravity mode (for menu check marks mostly).
This is some example OpenGL code you can use as a starting point for this tutorial.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//
// Set up the camera
//
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Determine the screen size so we can determine the aspect ratio
int width, height;
GetSize(width, height);
GLdouble aspectratio = GLdouble(width) / GLdouble(height);
// Set the camera parameters
gluPerspective(25., // Vertical field of view in degrees.
aspectratio, // The aspect ratio.
20., // Near clipping
1000.); // Far clipping
//
// Some standard parameters
//
// Enable depth test
glEnable(GL_DEPTH_TEST);
// Cull backfacing polygons
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
// Set the camera location
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
m_camera.gluLookAt();
// Enable lighting
glEnable(GL_LIGHTING);
float dimd = 0.5f;
GLfloat dim[] = {dimd, dimd, dimd, 1.0f};
GLfloat brightwhite[] = {1.f, 1.f, 1.f, 1.0f};
GLfloat lightpos0[] = {1.f, 0.5f, 1.2f, 0.f};
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_POSITION, lightpos0);
glLightfv(GL_LIGHT0, GL_DIFFUSE, brightwhite);
glLightfv(GL_LIGHT0, GL_AMBIENT, dim);
GLfloat red[] = {0.7f, 0.1f, 0.1f, 1.f};
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
GLdouble a[] = {0, 0, 2.5};
GLdouble b[] = {2.5, 0, -2.5};
GLdouble c[] = {-2.5, 0, -2.5};
GLdouble d[] = {0, 4, 0};
glBegin(GL_POLYGON);
glNormal3d(0.000000, -1.000000, 0.000000);
glVertex3dv(c);
glVertex3dv(b);
glVertex3dv(a);
glEnd();
glBegin(GL_POLYGON);
glNormal3d(0.861411, 0.269191, 0.430706);
glVertex3dv(d);
glVertex3dv(a);
glVertex3dv(b);
glEnd();
glBegin(GL_POLYGON);
glNormal3d(0.000000, 0.529999, -0.847998);
glVertex3dv(d);
glVertex3dv(b);
glVertex3dv(c);
glEnd();
glBegin(GL_POLYGON);
glNormal3d(-0.861411, 0.269191, 0.430706);
glVertex3dv(d);
glVertex3dv(c);
glVertex3dv(a);
glEnd();
glFlush();
