i
i
i
i
i
i
i
i
318 13. Programming 3D Graphics in Real Time
In response to the menu command to display the rendered model, a child
window is created, as shown in Listing 13.6. At this stage, the user can choose
to make a window which has a border and can be moved around the desktop
or one that has no border and fills the screen. Messages for the child window
are processed by its o wn message handling function, the key steps of which
are featured in Listing 13.7. The handler for the
WM PAINT message is where
most of the work for the application is done.
To allow the user to appear to pick up and look the object from all sides,
mouse m essages sent to the window’s handler function are used to change
the direction of the orientation variables. Listing 13.8 covers the main points
of how this is accomplished: on a press of the left mouse button, its input
HWND GLWindowPr(HINSTANCE hInstance, HWND hWndParent){
HWND hwnd;
if(!FullScreen){ // global variable
hwnd = CreateWindow( // a basic window
CLASSNAME1,CLASSNAME1, // macro with text
// class name
WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME,// standard decoration
64,64, 64+512, 64+512, // screen position
// and size
hWndParent,NULL,hInstance,NULL);
}
else{
hwnd=CreateWindowEx( // a full screen window
0,
"FSCREEN", // The class name for
"FSCREEN", // the window
WS_POPUP, // NO border menu etc.
0,
0,
GetSystemMetrics(SM_CXSCREEN), // the size of
// the display
GetSystemMetrics(SM_CYSCREEN), // screen
hWndParent, NULL, hInstance, NULL );
}
ShowWindow(hwnd,SW_SHOW);
InvalidateRect(hwnd,NULL,FALSE); // make sure contents
// are drawn
return hwnd;
}
Listing 13.6. Creating the OpenGL display window in either full-screen or windowed
mode.
i
i
i
i
i
i
i
i
13.1. Visualizing a Virtual World Using OpenGL 319
LRESULT WINAPI GLProcessWndProc( HWND hWnd, UINT msg,
WPARAM wParam, LPARAM lParam ){
// these variables are used by the mouse button and move messages to
// allow the user to change the viewpoint from which they view the model
static int mx,my,ms;
static RECT rc;
static BOOL bCapturedl=FALSE;
static BOOL bCapturedr=FALSE;
switch( msg ) {
case WM_CREATE:{
// OpenGL creation code with additional application specifics
// in a separate function
initializeGL(HWND hWnd);
}
break;
// if the uses changes the size of the window (which can’t happen in full
// screen mode) the OpenGL viewport must be adjusted to still fill the
// window’s client area
case WM_SIZE:
if(!FullScreen){
GetClientRect(hWnd, &rc);
glViewport(0, 0, rc.right,rc.bottom);
InvalidateRect(hWnd,NULL,FALSE);
}
break;
case WM_DESTROY:{
// standard OpenGL window closure
return 0;
}
case WM_PAINT:
DrawScene(hWnd); // draw the scene !!!!!!!!!!!
break;
..
// mouse handling messages
.. // watch for the "ESC" key pressed in full
case WM_CHAR:
// screen mode it is the only way to close the window
if (wParam == VK_ESCAPE)
PostMessage((HWND)GetWindowLong(hWnd,GWL_USERDATA),
WM_COMMAND,ID_CONTROL_CLOSE_WINDOW, 0);
// otherwise pass on other keys to main window
else PostMessage((HWND)GetWindowLong(hWnd,GWL_USERDATA),
WM_CHAR,wParam,lParam);
break;
default:
break;
}
return DefWindowProc( hWnd, msg, wParam, lParam );
}
Listing 13.7. The OpenGL window’s message handling function. The WM CREATE
message handles the standard stuff from Listing 13.1 and calls the function
initializeGL(..) to handle application-specific startup code.
i
i
i
i
i
i
i
i
320 13. Programming 3D Graphics in Real Time
// mouse messages - local STATIC variables mx,my,bCaptuered etc.
// declared earlier
..
case WM_LBUTTONDOWN:
if(bCapturedr)break;
SetCapture(hWnd); // all mouse messages are sent to this window
mx=(int)LOWORD(lParam); //
my=(int)HIWORD(lParam); // Get position of mouse in client area
// and dimensions
GetWindowRect(hWnd,&rc); //
bCapturedl=TRUE; // flag to indicated mouse is in capture mode
break;
case WM_RBUTTONDOWN: // similar to left button down message handling
... // code to handle right button
break;
case WM_MOUSEMOVE:{
double dx,dy;
if(bCapturedl){ // the left must button is DOWN so change view
mx=(short)LOWORD(lParam)-mx; my=(short)HIWORD(lParam)-my;
dx=(double)mx/(double)(rc.right-rc.left);
dy=(double)my/(double)(rc.bottom-rc.top);
if(GetAsyncKeyState(VK_CONTROL) & 0x8000){ // Zoom in or out if the
xpos_offset += (GLfloat)mx
*
0.01; // Control key held down
ypos_offset -= (GLfloat)my
*
0.01;
}
else{ // change the direction of view
round_angle += dx
*
360;
up_angle += dy
*
180;
}
InvalidateRect(hWnd,NULL,FALSE); // redraw
mx=(short)LOWORD(lParam); my=(short)HIWORD(lParam);
}
else if(bCapturedr){
.. // do much the same thing for the right mouse button
}
break;
case WM_LBUTTONUP:
if(bCapturedr)break; // don’t do anything if not captured
bCapturedl=FALSE;
ReleaseCapture(); // release the capture of mouse messages
break;
case WM_RBUTTONUP: // similar to left button down message handling
.. // code to handle up on right button
break;
..// other messages
Listing 13.8. Handling mouse messages allows users to change their viewpoint of the
mesh model
i
i
i
i
i
i
i
i
13.1. Visualizing a Virtual World Using OpenGL 321
GLvoid initializeGL(HWND hWnd){ // perform application specific GL startup
makeCheckeredImageMap(); // make a small image map for use in case of
// mapping error
initializeRender(hWnd); // set up the lighting and general
// viewing conditions
return;
}
#define checkImageWidth 64
#define checkImageHeight 64
#define CHECK_TEXTURE 1 // OpenGL texture identifier
GLubyte checkImage[checkImageWidth][checkImageHeight][3];
void makeCheckeredImageMap(void){
// This function uses the code from the OpenGL reference
// manual to make a small image map 64 x 64 with a checkerboard
// pattern. The map will be used as a drop in replacement
// for any maps that the mesh model uses but that can’t be created
// beause, for example, the image file is missing.
...
// The KEY OpenGL functions that are used to make a texture map follow
glBindTexture(GL_TEXTURE_2D,CHECK_TEXTURE); // define a 2D (surface) map
// this loads the texture into the hardware’s texture RAM
glTexImage2D(GL_TEXTURE_2D, 0, 3, checkImageWidth,
checkImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE,
&checkImage[0][0][0]);
// very many parameters can be applied to image maps e.g.
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
.. // consult the reference documentation for specific detail
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
... //
}
Listing 13.9. Additional OpenGL configuration for lighting, a default image map,
viewport and those camera properties (including its location at the origin, looking
along the z-axis) that dont change unless the user resizes the window.
is captured for exclusive use by this window (even if it moves outside the
window) and its screen position recorded. As the mouse moves, the difference
in its current position is used to adjust the orientation of the mesh by rotating
it about a horizontal and/or vertical axis. The right mouse button uses a
similar procedure to change the horizontal and vertical position of the model
relative to the viewpoint.
OpenGL initialization which uses the standard set-up shown in List-
ings 13.1 and 13.2 is extended by the application-specific function,
i
i
i
i
i
i
i
i
322 13. Programming 3D Graphics in Real Time
void initializeRender(HWND hWnd){
GLfloat d[]={1.0,1.0,1.0,1.0}; // diffuse light color
GLfloat a[]={0.1,0.1,0.1,1.0}; // ambient light color
GLfloat s[]={1.0,1.0,1.0,1.0}; // specular light color
GLfloat p[]={0.0,0.0,1.0,1.0}; // (x,y,z,w w=1 => positional light
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
glEnable(GL_LIGHT0); // enable the first (OGL has limited
// number of lights)
glLightfv(GL_LIGHT0,GL_DIFFUSE,d);// set the light parameters
glLightfv(GL_LIGHT0,GL_AMBIENT,a);
glLightfv(GL_LIGHT0,GL_SPECULAR,s);
glLightfv(GL_LIGHT0,GL_POSITION,p);
glLightf(GL_LIGHT0,GL_LINEAR_ATTENUATION,0.15);
glLightf(GL_LIGHT0,GL_QUADRATIC_ATTENUATION,0.05);
glClearDepth(1.0); // setup a Z buffer for hidden
// surface drawing
glEnable(GL_DEPTH_TEST); // a depth of 1.0 is fathest away
glClearColor(gbRed,gbGreen,gbBlue,1.0);
// The following code sets up the view point. It uses some UTILITY
// library functions
RECT oldrect;
GLfloat aspect;
glMatrixMode(GL_PROJECTION); // Going to define the viewing
// transformation
glLoadIdentity();
GetClientRect(hWnd, &oldrect);
aspect = (GLfloat) oldrect.right / (GLfloat) oldrect.bottom;
// A utility library function makes it easier to define a field of
// view 45 degrees,
// an aspect ratio that matches the window dimensions and two clipping planes.
// The clipping planes allow us to restrict which polygons are
// rendered to a volume
// space lying beyond the near_plane and on the viewpoint side of
// the far_plane.
gluPerspective( 45.0, aspect, near_plane, far_plane);
glMatrixMode( GL_MODELVIEW ); // Going to define the object transformation
glViewport(0, 0, oldrect.right,oldrect.bottom); // set to match the window
}
Listing 13.9. (continued).
initializeGL(..), that prepares the environment in which the model will
be viewed. It enables and specifies lighting. It defines the field of view and a
perspective projection with the viewpoint located at (0, 0, 0) and the viewer
looking along the z-axis; the y-axis is vertical by default. OpenGL uses a
right-handed coordinate system as illustrated in Figure 13.10.
All 3D coordinates are subject to a transformation, which is called the
GL MODELVIEW transformation. This allows hierarchical models to be built
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.222.132