In this lesson I shall introduce several functions and show you actual OpenGL
rendering in a program. Prior to showing you the code, however, I want to go
over a few things with you. This will give you a better understanding of what
is going on when you do see the code, so you don't stare at the screen
wondering what you're looking at. So, on with the show.
Transformations in OpenGL rely on the matrix for all mathematical computations. No, not the movie. Concentrate grasshopper. OpenGL has what is known as a matrix stack, which comes in handy for constructing models composed of many simple objects.
Transformations in OpenGL rely on the matrix for all mathematical computations. No, not the movie. Concentrate grasshopper. OpenGL has what is known as a matrix stack, which comes in handy for constructing models composed of many simple objects.
The modelview matrix defines the coordinate system that is being used to place and orient objects. It is a 4x4 matrix that is multiplied by vertices and transformations to create a new matrix that reflects the result of any transformations that have been applied to the vertices. When we want to modify the modelview matrix we use the command glMatrixMode(). We define this as
void glMatrixMode(GLenum mode);Before you call any transformation commands you MUST specify whether you want to modify the modelview matrix or the projection matrix. The argument for modifying the modelview matrix is GL_MODELVIEW. So the complete line would appear as:
void glMatrixMode(GL_MODELVIEW);Now we will look at translation. Translation allows you to move an object from one location to another within a 3D environment. The functions for this in OpenGL are glTranslatef() and glTranslated(). Here are their descriptions:
void glTranslatef(GLfloat x, GLfloat y, GLfloat z); void glTranslated(GLdouble x, GLdouble y, GLdouble z);Note that you must pass float types to glTranslatef() and double types to glTranslated(). X, Y, and Z represent the amount of translation on that axis.
Rotation in OpenGL is accomplished through the glRotate*() function, which is defined as
void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); void glRotated(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);Now let's take a look at these, and a few others, functions mentioned in a program. The following code is taken from OpenGL Game Programming and is commented by myself. If you have any problems building and using this code, feel free to contact me.
/* Steven Billington January 13, 2003 May 26, 2003 - UPDATE RobotOGL.cpp rod@cprogramming.com The following program creates a window and then uses multiple OpenGL functions to display a animated robot constructed of different size cubes. To compile this code you must make the proper library links in project--->settings. I apologize for any amount of scattered code or mis-formatting that printing this may occur. Please feel free to email me at the address above for the .cpp file. */ /* These are what we refer to as Pre-processor Directives. In order for certain functions in C++ to operate you must include certain header files. Each header file below contains different functions needed throughout this program. */ #pragma comment(linker, "/subsystem:windows") #include <windows.h> #include <gl/gl.h> #include <gl/glu.h> #include <gl/glaux.h> /* Here we find a few global variables. While i don't really like to use global variables, i found them very handy for this particular program. These variables will control angles, fullscreen, and the global device context. */ HDC g_HDC; float angle = 0.0f; float legAngle[2] = {0.0f, 0.0f}; float armAngle[2] = {0.0f, 0.0f}; bool fullScreen = false; /* Function: DrawCube Purpose: As the name would suggest, this is the function for drawing the cubes. */ void DrawCube(float xPos, float yPos, float zPos) { glPushMatrix(); glBegin(GL_POLYGON); /* This is the top face*/ glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(0.0f, 0.0f, -1.0f); glVertex3f(-1.0f, 0.0f, -1.0f); glVertex3f(-1.0f, 0.0f, 0.0f); /* This is the front face*/ glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(-1.0f, 0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 0.0f); glVertex3f(0.0f, -1.0f, 0.0f); /* This is the right face*/ glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(0.0f, -1.0f, 0.0f); glVertex3f(0.0f, -1.0f, -1.0f); glVertex3f(0.0f, 0.0f, -1.0f); /* This is the left face*/ glVertex3f(-1.0f, 0.0f, 0.0f); glVertex3f(-1.0f, 0.0f, -1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glVertex3f(-1.0f, -1.0f, 0.0f); /* This is the bottom face*/ glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(0.0f, -1.0f, -1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glVertex3f(-1.0f, -1.0f, 0.0f); /* This is the back face*/ glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(-1.0f, 0.0f, -1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glVertex3f(0.0f, -1.0f, -1.0f); glEnd(); glPopMatrix(); } /* Function: DrawArm Purpose: This function draws the arm for the robot. */ void DrawArm(float xPos, float yPos, float zPos) { glPushMatrix(); /* Sets color to red*/ glColor3f(1.0f, 0.0f, 0.0f); glTranslatef(xPos, yPos, zPos); /* Creates 1 x 4 x 1 cube*/ glScalef(1.0f, 4.0f, 1.0f); DrawCube(0.0f, 0.0f, 0.0f); glPopMatrix(); } /* Function: DrawHead Purpose: This function will create the head for the robot. */ void DrawHead(float xPos, float yPos, float zPos) { glPushMatrix(); /* Sets color to white*/ glColor3f(1.0f, 1.0f, 1.0f); glTranslatef(xPos, yPos, zPos); /* Creates 2 x 2 x 2 cube*/ glScalef(2.0f, 2.0f, 2.0f); DrawCube(0.0f, 0.0f, 0.0f); glPopMatrix(); } /* Function: DrawTorso Purpose: Function will do as suggested and draw a torso for our robot. */ void DrawTorso(float xPos, float yPos, float zPos) { glPushMatrix(); /* Sets color to blue*/ glColor3f(0.0f, 0.0f, 1.0f); glTranslatef(xPos, yPos, zPos); /* Creates 3 x 5 x 1 cube*/ glScalef(3.0f, 5.0f, 1.0f); DrawCube(0.0f, 0.0f, 0.0f); glPopMatrix(); } /* Function: DrawLeg Purpose: Not to sound repetitve, but as suggested this function will draw our robots legs. */ void DrawLeg(float xPos, float yPos, float zPos) { glPushMatrix(); /* Sets color to yellow*/ glColor3f(1.0f, 1.0f, 0.0f); glTranslatef(xPos, yPos, zPos); /* Creates 1 x 5 x 1 cube*/ glScalef(1.0f, 5.0f, 1.0f); DrawCube(0.0f, 0.0f, 0.0f); glPopMatrix(); } /* Function: DrawRobot Purpose: Function to draw our entire robot */ void DrawRobot(float xPos, float yPos, float zPos) { /* Variables for state of robots legs. True means the leg is forward, and False means the leg is back. The same applies to the robots arm states. */ static bool leg1 = true; static bool leg2 = false; static bool arm1 = true; static bool arm2 = false; glPushMatrix(); /* This will draw our robot at the desired coordinates. */ glTranslatef(xPos, yPos, zPos); /* These three lines will draw the various components of our robot. */ DrawHead(1.0f, 2.0f, 0.0f); DrawTorso(1.5f, 0.0f, 0.0f); glPushMatrix(); /* If the arm is moving forward we will increase the angle; otherwise, we will decrease the angle. */ if (arm1) { armAngle[0] = armAngle[0] + 1.0f; } else { armAngle[0] = armAngle[0] - 1.0f; } /* Once the arm has reached its max angle in one direction, we want it to reverse and change direction. */ if (armAngle[0] >= 15.0f) { arm1 = false; } if (armAngle[0] <= 15.0f) { arm1 = true; } /* Here we are going to move the arm away from the torso and rotate. This will create a walking effect. */ glTranslatef(0.0f, -0.5f, 0.0f); glRotatef(armAngle[0], 1.0f, 0.0f, 0.0f); DrawArm(2.5f, 0.0f, -0.5f); glPopMatrix(); glPushMatrix(); /* If the arm is moving forward we will increase the angle, otherwise we will decrease the angle */ if (arm2) { armAngle[1] = armAngle[1] + 1.0f; } else { armAngle[1] = armAngle[1] - 1.0f; } /* Here we are going to move the arm away from the torso and rotate. This will create a walking effect. */ glTranslatef(0.0f, -0.5f, 0.0f); glRotatef(armAngle[1], 1.0f, 0.0f, 0.0f); DrawArm(-1.5f, 0.0f, -0.5f); glPopMatrix(); /* Now its time to rotate the legs relative to the robots position in the world, this is the first leg, ie the right one. */ glPushMatrix(); /* If the leg is moving forward we will increase the angle; otherwise, we will decrease the angle. */ if (leg1) { legAngle[0] = legAngle[0] + 1.0f; } else { legAngle[0] = legAngle[0] - 1.0f; } /* Once the leg has reached its max angle in one direction, we want it to reverse and change direction. */ if (legAngle[0] >= 15.0f) { leg1 = false; } if (legAngle[0] <= -15.0f) { leg1 = true; } /* Here we are going to move the leg away from the torso and rotate. This will create a walking effect. */ glTranslatef(0.0f, -0.5f, 0.0f); glRotatef(legAngle[0], 1.0f, 0.0f, 0.0f); /* Time to draw the leg. */ DrawLeg(-0.5f, -5.0f, -0.5f); glPopMatrix(); /* Same as above, for the left leg. */ glPushMatrix(); /* If the leg is moving forward we will increase the angle, otherwise we will decrease the angle */ if (leg2) { legAngle[1] = legAngle[1] + 1.0f; } else { legAngle[1] = legAngle[1] - 1.0f; } /* Once the leg has reached its max angle in one direction, we want it to reverse and change direction. */ if (legAngle[1] >= 15.0f) { leg2 = false; } if (legAngle[1] <= -15.0f) { leg2 = true; } /* Here we are going to move the leg away from the torso and rotate. This will create a walking effect. */ glTranslatef(0.0f, -0.5f, 0.0f); glRotatef(legAngle[1], 1.0f, 0.0f, 0.0f); DrawLeg(1.5f, -5.0f, -0.5f); glPopMatrix(); glPopMatrix(); } /* Function: Render Purpose: This function will be responsible for the rendering, got to love my descriptive function names : ) */ void Render() { /* Enable depth testing */ glEnable(GL_DEPTH_TEST); /* Heres our rendering. Clears the screen to black, clear the color and depth buffers, and reset our modelview matrix. */ glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); /* Increase rotation angle counter */ angle = angle + 1.0f; /* Reset after we have completed a circle */ if (angle >= 360.0f) { angle = 0.0f; } glPushMatrix(); glLoadIdentity(); /* Move to 0,0,-30 , rotate the robot on its y axis, draw the robot, and dispose of the current matrix. */ glTranslatef(0.0f, 0.0f, -30.0f); glRotatef(angle, 0.0f, 1.0f, 0.0f); DrawRobot(0.0f, 0.0f, 0.0f); glPopMatrix(); glFlush(); /* Bring back buffer to foreground */ SwapBuffers(g_HDC); } //function to set the pixel format for the device context /* Function: SetupPixelFormat Purpose: This function will be responsible for setting the pixel format for the device context. */ void SetupPixelFormat(HDC hDC) { /* Pixel format index */ int nPixelFormat; static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), //size of structure 1, //default version PFD_DRAW_TO_WINDOW | //window drawing support PFD_SUPPORT_OPENGL | //opengl support PFD_DOUBLEBUFFER, //double buffering support PFD_TYPE_RGBA, //RGBA color mode 32, //32 bit color mode 0, 0, 0, 0, 0, 0, //ignore color bits 0, //no alpha buffer 0, //ignore shift bit 0, //no accumulation buffer 0, 0, 0, 0, //ignore accumulation bits 16, //16 bit z-buffer size 0, //no stencil buffer 0, //no aux buffer PFD_MAIN_PLANE, //main drawing plane 0, //reserved 0, 0, 0 }; //layer masks ignored /* Choose best matching format*/ nPixelFormat = ChoosePixelFormat(hDC, &pfd); /* Set the pixel format to the device context*/ SetPixelFormat(hDC, nPixelFormat, &pfd); } /* Windows Event Procedure Handler */ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { /* Rendering and Device Context variables are declared here. */ static HGLRC hRC; static HDC hDC; /* Width and Height for the window our robot is to be displayed in. */ int width, height; switch(message) { case WM_CREATE: //window being created hDC = GetDC(hwnd); //get current windows device context g_HDC = hDC; SetupPixelFormat(hDC); //call our pixel format setup function /* Create rendering context and make it current */ hRC = wglCreateContext(hDC); wglMakeCurrent(hDC, hRC); return 0; break; case WM_CLOSE: //window is closing /* Deselect rendering context and delete it*/ wglMakeCurrent(hDC, NULL); wglDeleteContext(hRC); /* Send quit message to queue*/ PostQuitMessage(0); return 0; break; case WM_SIZE: /* Retrieve width and height*/ height = HIWORD(lParam); width = LOWORD(lParam); /* Don't want a divide by 0*/ if (height == 0) { height = 1; } /* Reset the viewport to new dimensions*/ glViewport(0, 0, width, height); /* Set current Matrix to projection*/ glMatrixMode(GL_PROJECTION); glLoadIdentity(); //reset projection matrix /* Time to calculate aspect ratio of our window. */ gluPerspective(54.0f, (GLfloat)width/(GLfloat)height, 1.0f, 1000.0f); glMatrixMode(GL_MODELVIEW); //set modelview matrix glLoadIdentity(); //reset modelview matrix return 0; break; default: break; } return (DefWindowProc(hwnd, message, wParam, lParam)); } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX windowClass; //window class HWND hwnd; //window handle MSG msg; //message bool done; //flag for completion of app DWORD dwExStyle; //window extended style DWORD dwStyle; //window style RECT windowRect; /* Screen/display attributes*/ int width = 800; int height = 600; int bits = 32; windowRect.left =(long)0; //set left value to 0 windowRect.right =(long)width; //set right value to requested width windowRect.top =(long)0; //set top value to 0 windowRect.bottom =(long)height;//set bottom value to requested height /* Fill out the window class structure*/ windowClass.cbSize = sizeof(WNDCLASSEX); windowClass.style = CS_HREDRAW | CS_VREDRAW; windowClass.lpfnWndProc = WndProc; windowClass.cbClsExtra = 0; windowClass.cbWndExtra = 0; windowClass.hInstance = hInstance; windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); windowClass.hCursor = LoadCursor(NULL, IDC_ARROW); windowClass.hbrBackground = NULL; windowClass.lpszMenuName = NULL; windowClass.lpszClassName = "MyClass"; windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO); /* Register window class*/ if (!RegisterClassEx(&windowClass)) { return 0; } /* Check if fullscreen is on*/ if (fullScreen) { DEVMODE dmScreenSettings; memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); dmScreenSettings.dmSize = sizeof(dmScreenSettings); dmScreenSettings.dmPelsWidth = width; //screen width dmScreenSettings.dmPelsHeight = height; //screen height dmScreenSettings.dmBitsPerPel = bits; //bits per pixel dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN != DISP_CHANGE_SUCCESSFUL)) { /* Setting display mode failed, switch to windowed*/ MessageBox(NULL, "Display mode failed", NULL, MB_OK); fullScreen = false; } } /* Check if fullscreen is still on*/ if (fullScreen) { dwExStyle = WS_EX_APPWINDOW; //window extended style dwStyle = WS_POPUP; //windows style ShowCursor(FALSE); //hide mouse pointer } else { dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; //window extended style dwStyle = WS_OVERLAPPEDWINDOW; //windows style } AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle); /* Class registerd, so now create our window*/ hwnd = CreateWindowEx(NULL, "MyClass", //class name "OpenGL Robot", //app name dwStyle | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0, //x and y coords windowRect.right - windowRect.left, windowRect.bottom - windowRect.top,//width, height NULL, //handle to parent NULL, //handle to menu hInstance, //application instance NULL); //no xtra params /* Check if window creation failed (hwnd = null ?)*/ if (!hwnd) { return 0; } ShowWindow(hwnd, SW_SHOW); //display window UpdateWindow(hwnd); //update window done = false; //initialize loop condition variable /* Main message loop*/ while (!done) { PeekMessage(&msg, hwnd, NULL, NULL, PM_REMOVE); if (msg.message == WM_QUIT) //did we receive a quit message? { done = true; } else { Render(); TranslateMessage(&msg); DispatchMessage(&msg); } } if (fullScreen) { ChangeDisplaySettings(NULL, 0); ShowCursor(TRUE); } return msg.wParam; }That's a lot of code! Spend some time studying the example, practice a bit, and then we will proceed to coming lesson, where more of this code will be explained. Also we will cover Projections.
Next: Projections in OpenGL
No comments:
Post a Comment
if You Need Any Help Then Write Us:We Come Back With Solution