Another nice morning to just get up and write...
As I promised last week, I did some reading on Open Gl, and I made a new program which displays now a dancing robot on the screen. This program was actually much more easier to do than the last one I showed here, since I finally understood how to use the functions glPushMatrix and glPopMatrix. Why are these two functions important ?
If you decide not to implement them, and just end up using glTranslatef(xPos,yPos-10,zPos) or glScale etc, what´s going to be happening is that you`re going to be moving your whole scene or scaling your whole scene, so you will loose power in saying what it is you want to move or scale. Let´s say you already drew correctly the robot´s head and torso, and you just wanted to add the robot´s right arm, you wnat the piece of code you already drew to stay put, you don´t need it to be moving around, you woulkd just have to move the new arm figure to upper shoulder. To acomplish this, you use Pop and Push. You are actually drawing once again the robot, but the stack is keeping the order in which the robot to be drawn, and it just moves what you ask it to, what you push into or pop out of the stack.
Anyway, perhaps it will be a lot more clearer with a piece of code:
.....................................................................................................................................................................
#pragma comment(linker, "/subsystem:windows")
#include
#include
#include
#include
/* . 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: DrawSquare
Purpose: As the name would suggest, this is
the function for drawing the cubes.
*/
void
DrawSquare(float xPos, float yPos, float zPos)
{
glPushMatrix();
glBegin(GL_POLYGON);
/* 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);
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);
DrawSquare(0.0f, 0.0f, 0.0f);
glPopMatrix();
/* This will draw the gross part of the arm.*/
glPushMatrix();
/* Sets color to red*/
glColor3f(0.0f, 1.0f, 0.0f);
glTranslatef(xPos+1, yPos-4.0f, zPos);
/* Creates 1 x 4 x 1 cube*/
glScalef(2.0f, 2.0f, 1.0f);
DrawSquare(0.0f, 0.0f, 0.0f);
glPopMatrix();
/* This will draw the robot´s hand*/
glPushMatrix();
/* Sets color to red*/
glColor3f(1.0f, 1.0f, 1.0f);
glTranslatef(xPos+1, yPos-6.0f, zPos);
/* Creates 1 x 4 x 1 cube*/
glScalef(1.0f, 1.0f, 1.0f);
DrawSquare(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);
DrawSquare(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);
DrawSquare(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(0.0f, 0.0f, 1.0f);
glTranslatef(xPos, yPos, zPos);
/* Creates 1 x 5 x 1 cube*/
glScalef(1.0f, 5.0f, 1.0f);
DrawSquare(1.0f, 0.0f, 0.0f);
glPopMatrix();
/*This will draw the gross part of the leg for the robot.*/
glPushMatrix();
glColor3f(1.0f,1.0f,1.0f);
glTranslatef(xPos,yPos-5,zPos);
glScalef(2.0f,5.0f,1.0f);
DrawSquare(0.0f, 0.0f, 0.0f);
glPopMatrix();
/*This will draw the robot´s foot*/
glPushMatrix();
glColor3f(0.0f,1.0f,0.0f);
glTranslatef(xPos,yPos-10,zPos);
glScalef(3.0f,2.0f,1.0f);
DrawSquare(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 revieve a quit message?
{
done =
true;
}
else
{
Render();
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
if (fullScreen)
{
ChangeDisplaySettings(NULL, 0);
ShowCursor(TRUE);
}
return msg.wParam;
}
1 comment:
OMG, tron!!!! Robots!! and Dancing!!! yei!!! DJ come on, scratch that thing!!!!
Fluffy.
Post a Comment