使用OpenGl绘制可以行走的机器人
1、练习使用OpenGl的库函数;
2、学习OpenGl的动画制作;
VS2012+OpenGl
视频展示+后面有图+后面有源码
1、设计机器人形状:帽子+头部+躯体+手臂+大腿+小腿;其中,为了简单起见这些组成部分都是使用的立方体来表示。首先绘制一个单位立方体:
//绘制单位立方体
void DrawCube(float xPos,float yPos,float zPos)
{
glPushMatrix();
glTranslatef(xPos,yPos,zPos);
glBegin(GL_POLYGON);
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);
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);
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);
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);
glVertex3f(0.0f,-1.0f,0.0f); //底面
glVertex3f(0.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,0.0f);
glVertex3f(0.0f,0.0f,-1.0f); //背面
glVertex3f(-1.0f,0.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(0.0f,-1.0f,-1.0f);
glEnd();
glPopMatrix();
}
然后通过OpenGl的glScalef(3.6f,0.8f,3.6f);函数来控制立方体的大小,从而使得机器人看上去比较协调。例如,绘制帽子:
//帽子
glPushMatrix();
glColor3f(0.6f,0.4f,0.12f); //褐色
glTranslatef(xPos+0.58,yPos+1.0,zPos+1.1);
glScalef(3.6f,0.8f,3.6f);
DrawCube(0.0f,0.0f,0.0f);
glPopMatrix();
2、将机器人的各个部分组装起来,主要是控制各个立方体的位置。这里只是简单的调试唯一参数,是机器人看起来比较正常。
3、让机器人手臂和腿部动起来,通过设置OpenGl的双缓冲区以及调用函数就可以重复绘制机器人同时改变机器人的位移,并且使用glRotatef函数控制机器人的手臂和腿部使其发生一定角度的旋转,从而达到摆臂行走的动作,这样就完成了运动。
//向前为true
bool right_hand = true;
bool right_leg = false;
int time = 0;
int max_time = 1000; //设定换臂时间
//画机器人
void DrawRobot(float xPos,float yPos,float zPos){
//绘制头
glPushMatrix();
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
DrawHead(-5.0f,2.5f,1.0f);
glPopMatrix();
glPushMatrix();
//右臂
if(right_hand){
glRotatef(-30.0f,-1.0,0.0,0.0);
}else{
glRotatef(30.0f,-1.0,0.0,0.0);
}
DrawUpArm(-3.2f,0.0f,0.25f);
glPopMatrix();
//躯体
DrawBody(-4.5f,0.0f,1.0f);
//左臂
glPushMatrix();
if(right_hand){
glRotatef(30.0f,-1.0,0.0,0.0);
if(time==max_time) right_hand = !right_hand;
}else{
glTranslatef(-0.5f,0.0f,-1.0f);
glRotatef(-30.0f,-1.0,0.0,0.0);
if(time==max_time) right_hand = !right_hand;
}
DrawUpArm(-8.0f,0.0f,0.25f);
glPopMatrix();
//右腿
glPushMatrix();
if(right_leg){
glRotatef(-15.0f,-1.0,0.0,0.0);
}else{
//glRotatef(15.0f,-1.0,0.0,0.0);
}
DrawUpLeg(-4.5f,-5.8f,0.25f);
glPopMatrix();
glPushMatrix();
if(right_leg){
glRotatef(-15.0f,-1.0,0.0,0.0);
}else{
//glRotatef(13.0f,-1.0,0.0,0.0);
}
DrawDownLeg(-4.5f,-10.2f,0.25f);
glPopMatrix();
//左腿
glPushMatrix();
if(right_leg){
//glRotatef(15.0f,-1.0,0.0,0.0);
}else{
glRotatef(-15.0f,-1.0,0.0,0.0);
}
DrawUpLeg(-6.5f,-5.8f,0.25f);
glPopMatrix();
glPushMatrix();
if(right_leg){
//glRotatef(15.0f,-1.0,0.0,0.0);
if(time==max_time) right_leg = !right_leg;
}else{
glRotatef(-15.0f,-1.0,0.0,0.0);
if(time==max_time) right_leg = !right_leg;
}
DrawDownLeg(-6.5f,-10.2f,0.25f);
glPopMatrix();
if(time==max_time) time = 0;
else time++;
}
double step =-60.0;
//处理场景的绘制
void Render(){
//在此处绘制
glClearColor(0.0f,0.0f,0.0f,0.0f); //设置清理色为黑色
glClear(GL_COLOR_BUFFER_BIT); //清理颜色/深度缓存
glPushMatrix(); //将当前矩阵压入矩阵堆栈
glLoadIdentity(); //复位矩阵
step+=0.001;
glTranslatef(0.0f,5.0f,step); //平移至(0,0,-30)
//glRotatef(90,0.0f,1.0f,0.0f);//绕其y轴旋转机器人
//glRotatef(15,1.0f,0.0f,0.0f);
DrawRobot(0.0f,0.0f,0.0f); //绘制机器人
glPopMatrix(); //弹出当前矩阵
glFlush();
SwapBuffers(g_HDC); //交换前后缓存
}
#define WIN32_LEAN_AND_MEAN
#include
#include
#include
#pragma comment(lib, "openGL32.lib")
#pragma comment(lib, "glu32.lib")
float angle=0.0f;
HDC g_HDC;
bool fullScreen=false;
//绘制单位立方体
void DrawCube(float xPos,float yPos,float zPos)
{
glPushMatrix();
glTranslatef(xPos,yPos,zPos);
glBegin(GL_POLYGON);
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);
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);
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);
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);
glVertex3f(0.0f,-1.0f,0.0f); //底面
glVertex3f(0.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,0.0f);
glVertex3f(0.0f,0.0f,-1.0f); //背面
glVertex3f(-1.0f,0.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(0.0f,-1.0f,-1.0f);
glEnd();
glPopMatrix();
}
//绘制头部
void DrawHead(float xPos,float yPos,float zPos)
{
//帽子
glPushMatrix();
glColor3f(0.6f,0.4f,0.12f); //褐色
glTranslatef(xPos+0.58,yPos+1.0,zPos+1.1);
glScalef(3.6f,0.8f,3.6f);
DrawCube(0.0f,0.0f,0.0f);
glPopMatrix();
//头
glPushMatrix();
glColor3f(1.0f,1.0f,1.0f); //白色
glTranslatef(xPos,yPos,zPos);
glScalef(2.0f,2.0f,2.0f); //机器人的头是一个2*2*2的立方体
DrawCube(0.0f,0.0f,0.0f);
glPopMatrix();
}
//绘制躯干
void DrawBody(float xPos,float yPos,float zPos)
{
glPushMatrix();
glColor3f(0.0f,0.0f,1.0f); //蓝色
glTranslatef(xPos,yPos,zPos);
glScalef(3.0f,5.5f,2.0f); //机器人的躯干是一个3*5.5*2的立方体
DrawCube(0.0f,0.0f,0.0f);
glPopMatrix();
}
//绘制手臂
void DrawUpArm(float xPos,float yPos,float zPos){
glPushMatrix();
glTranslatef(xPos,yPos,zPos);
glColor3f(0.0f,1.0f,1.0f); //青色
glScalef(0.8f,5.5f,0.8f); //机器人的上手臂是一个1*5.5*1的立方体
DrawCube(0.0f,0.0f,0.0f);
glPopMatrix();
}
//绘制大腿
void DrawUpLeg(float xPos,float yPos,float zPos){
glPushMatrix();
glColor3f(0.18f,0.56f,1.0f); //蓝色
glTranslatef(xPos,yPos,zPos);
glScalef(1.0f,4.0f,1.0f); //机器人的腿是一个1*4*1的立方体
DrawCube(0.0f,0.0f,0.0f);
glPopMatrix();
}
//绘制小腿
void DrawDownLeg(float xPos,float yPos,float zPos){
glPushMatrix();
glColor3f(0.18f,0.56f,1.0f); //蓝色
glTranslatef(xPos,yPos,zPos);
glScalef(1.0f,3.0f,1.0f); //机器人的腿是一个1*3*1的立方体
DrawCube(0.0f,0.0f,0.0f);
glPopMatrix();
}
//向前为true
bool right_hand = true;
bool right_leg = false;
int time = 0;
int max_time = 1000; //设定换臂时间
//画机器人
void DrawRobot(float xPos,float yPos,float zPos){
//绘制头
glPushMatrix();
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
DrawHead(-5.0f,2.5f,1.0f);
glPopMatrix();
glPushMatrix();
//右臂
if(right_hand){
glRotatef(-30.0f,-1.0,0.0,0.0);
}else{
glRotatef(30.0f,-1.0,0.0,0.0);
}
DrawUpArm(-3.2f,0.0f,0.25f);
glPopMatrix();
//躯体
DrawBody(-4.5f,0.0f,1.0f);
//左臂
glPushMatrix();
if(right_hand){
glRotatef(30.0f,-1.0,0.0,0.0);
if(time==max_time) right_hand = !right_hand;
}else{
glTranslatef(-0.5f,0.0f,-1.0f);
glRotatef(-30.0f,-1.0,0.0,0.0);
if(time==max_time) right_hand = !right_hand;
}
DrawUpArm(-8.0f,0.0f,0.25f);
glPopMatrix();
//右腿
glPushMatrix();
if(right_leg){
glRotatef(-15.0f,-1.0,0.0,0.0);
}else{
//glRotatef(15.0f,-1.0,0.0,0.0);
}
DrawUpLeg(-4.5f,-5.8f,0.25f);
glPopMatrix();
glPushMatrix();
if(right_leg){
glRotatef(-15.0f,-1.0,0.0,0.0);
}else{
//glRotatef(13.0f,-1.0,0.0,0.0);
}
DrawDownLeg(-4.5f,-10.2f,0.25f);
glPopMatrix();
//左腿
glPushMatrix();
if(right_leg){
//glRotatef(15.0f,-1.0,0.0,0.0);
}else{
glRotatef(-15.0f,-1.0,0.0,0.0);
}
DrawUpLeg(-6.5f,-5.8f,0.25f);
glPopMatrix();
glPushMatrix();
if(right_leg){
//glRotatef(15.0f,-1.0,0.0,0.0);
if(time==max_time) right_leg = !right_leg;
}else{
glRotatef(-15.0f,-1.0,0.0,0.0);
if(time==max_time) right_leg = !right_leg;
}
DrawDownLeg(-6.5f,-10.2f,0.25f);
glPopMatrix();
if(time==max_time) time = 0;
else time++;
}double step = -60.0;
//处理场景的绘制
void Render(){
//在此处绘制
glClearColor(0.0f,0.0f,0.0f,0.0f); //设置清理色为黑色
glClear(GL_COLOR_BUFFER_BIT); //清理颜色/深度缓存
glPushMatrix(); //将当前矩阵压入矩阵堆栈
glLoadIdentity(); //复位矩阵
glTranslatef(0.0f,5.0f,step+0.001); //平移至(0,0,-30)
//glRotatef(90,0.0f,1.0f,0.0f);//绕其y轴旋转机器人
//glRotatef(15,1.0f,0.0f,0.0f);
DrawRobot(0.0f,0.0f,0.0f); //绘制机器人
glPopMatrix(); //弹出当前矩阵
glFlush();
SwapBuffers(g_HDC); //交换前后缓存
}
//为设备环境设置像素格式的函数
void SetupPixelFormat(HDC hDC)
{
int nPixelFormat;
static PIXELFORMATDESCRIPTOR pfd=
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
32,
0,0,0,0,0,0,
0,
0,
0,
0,0,0,0,
16,
0,
0,
PFD_MAIN_PLANE,
0,
0,0,0
};
nPixelFormat=ChoosePixelFormat(hDC,&pfd);
SetPixelFormat(hDC,nPixelFormat,&pfd);
}
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
static HGLRC hRC;
static HDC hDC;
int width,height;
switch(message)
{
case WM_CREATE:
hDC=GetDC(hwnd);
g_HDC=hDC;
SetupPixelFormat(hDC);
hRC=wglCreateContext(hDC);
wglMakeCurrent(hDC,hRC);
return 0;
break;
case WM_CLOSE:
wglMakeCurrent(hDC,NULL);
wglDeleteContext(hRC);
PostQuitMessage(0);
return 0;
break;
case WM_SIZE:
height=HIWORD(lParam);
width=LOWORD(lParam);
if(height==0)
height=1;
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(54.0f,(GLfloat)width/(GLfloat)height,1.0f,1000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
return 0;
break;
default:
break;
}
return (DefWindowProc(hwnd,message,wParam,lParam));
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
WNDCLASSEX windowClass;
HWND hwnd;
MSG msg;
bool done;
DWORD dwExStyle;
DWORD dwStyle;
RECT windowRect;
int width=800;
int height=600;
int bits=32;
windowRect.left=(long)0;
windowRect.right=(long)width;
windowRect.top=(long)0;
windowRect.bottom=(long)height;
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);
if(!RegisterClassEx(&windowClass))
return 0;
if(fullScreen)
{
DEVMODE dmScreenSettings;
memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
dmScreenSettings.dmSize=sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth=width;
dmScreenSettings.dmPelsHeight=height;
dmScreenSettings.dmBitsPerPel=bits;
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
if(ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
{
MessageBox(NULL,"Display mode failed",NULL,MB_OK);
fullScreen=FALSE;
}
}
if(fullScreen)
{
dwExStyle=WS_EX_APPWINDOW;
dwStyle=WS_POPUP;
ShowCursor(FALSE);
}
else
{
dwExStyle=WS_EX_APPWINDOW|WS_EX_WINDOWEDGE;
dwStyle=WS_OVERLAPPEDWINDOW;
}
AdjustWindowRectEx(&windowRect,dwStyle,FALSE,dwExStyle);
hwnd=CreateWindowEx(dwExStyle,"MyClass",
"Robot",
dwStyle|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,
0,0,
windowRect.right-windowRect.left,
windowRect.bottom-windowRect.top,
NULL,
NULL,
hInstance,
NULL);
if(!hwnd)
return 0;
ShowWindow(hwnd,SW_SHOW);
UpdateWindow(hwnd);
done=false;
while(!done)
{
PeekMessage(&msg,hwnd,NULL,NULL,PM_REMOVE);
if(msg.message==WM_QUIT)
{
done=true;
}
else
{
Render();
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
if(fullScreen)
{
ChangeDisplaySettings(NULL,0);
ShowCursor(TRUE);
}
return msg.wParam;
}