您的位置:首页 > 运维架构

OpenGL织梦之旅【第四章】第2节.简单的3D动画

2013-03-04 15:36 393 查看
上一小节中,我们已经成功地搭建好了一个“小剧场”,“观众席”已经设置好了,但是“演员”还没有到位。所以这一小节,我们就来请一些“演员”,让他们做一些“动作”。

还记得读取纹理那章的内容吧~2D纹理在这里同样是可以使用的。为了方便,我把LoadBitmap函数放到了"bmpLoader.h"中,这样方便调用。

在bmpLoader.h中:

#include <windows.h>
#define BITMAP_ID 0x4D42
int LoadBitmap(const char *file)
{
/*。。。*/
}


具体的函数内容就不写出来了。

在init()函数中,调用boxTexture=LoadBitmap("Box.bmp");把纹理保存到boxTexture中。
再重写一下DrawBox函数,给他加上3个参数,让他可以在指定位置画箱子,添上纹理

void DrawBox(float bx,float by,float bz)
{
glPushAttrib(GL_CURRENT_BIT);
glPushMatrix();
glTranslatef(bx,by,bz);	//在指定位置画箱子
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, boxTexture);    //指定纹理
glBegin(GL_QUADS);

glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);

glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);

glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);

glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);

glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);

glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
glEnd();
glPopMatrix();
glPopAttrib();
glDisable(GL_TEXTURE_2D);
}


随后,只需要调用void
DrawBox(
float bx,float by,float
bz)
,就能够在指定的位置画箱子了。为了管理方便,再定义一个结构体,用来保存3维坐标。

演员的坐标就用这个结构体来管理。

所以在定义3个全局point3D,在init函数中,给他们个初值。

struct point3D
{
double x;
double y;
double z;
};

point3D box[3];
void init()
{
glClearColor(0.0,0.0,0.0,0.0);
glEnable(GL_DEPTH_TEST);
setAll(20,1.75,0,0,1.75,0,0,1,0);
boxTexture=LoadBitmap("Box.bmp");
box[0].x=-2.0;
box[0].y=0.5;
box[0].z=0.0;
box[1].x=0.0;
box[1].y=0.5;
box[1].z=0.0;
box[2].x=2.0;
box[2].y=0.5;
box[2].z=0.0;
}


这个时候,编译运行就能看见,“演员”已经就位了!
(按a和d键可以调整视角)



但是,我们还没有给他“剧本”,所以他们是不会动的!

在这个init()-Update()-Draw()框架中,Update()函数会每分钟执行很多次,Update来负责这个给定剧本工作的。

void Update()
{
static int count;
if (count >= 0)
{
box[0].y+=0.02;
box[1].y+=0.04;
box[2].y+=0.08;
}
else
{
box[0].y-=0.02;
box[1].y-=0.04;
box[2].y-=0.08;
}
count++;
if (count == 100)
count=-count;
glLoadIdentity();
setLookAt();
glutPostRedisplay();
}


给定一个静态变量count,用于更新箱子的位置。

现在再编译运行就能看到效果了,这就是简单的3D动画。



附本节全部代码:

#include <GL/glut.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <iostream>
#include "bmpLoader.h"
#define PI 3.1415926
int WinWidth,WinHeight;
double posX,posY,posZ,viewX,viewY,viewZ,upX,upY,upZ;
struct point3D
{
double x;
double y;
double z;
};
point3D box[3];
GLint boxTexture;
void setAll(double px,double py,double pz,
double vx,double vy,double vz,
double ux,double uy,double uz)
{
posX=px;
posY=py;
posZ=pz;
viewX=vx;
viewY=vy;
viewZ=vz;
upX=ux;
upY=uy;
upZ=uz;
}
void setLookAt()
{
gluLookAt(posX,posY,posZ,
viewX,viewY,viewZ,
upX,upY,upZ);
}
void setPos(double x,double y,double z)
{
posX=x;
posY=y;
posZ=z;
}
void DrawBox(float bx,float by,float bz)
{
glPushAttrib(GL_CURRENT_BIT);
glPushMatrix();
glTranslatef(bx,by,bz);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, boxTexture);
glBegin(GL_QUADS);

glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);

glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);

glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);

glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);

glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);

glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glEnd();
glPopMatrix();
glPopAttrib();
glDisable(GL_TEXTURE_2D);
}
void DrawGrid()
{
glPushAttrib(GL_CURRENT_BIT);
glLineWidth(2);
glColor3f(0.0,1.0,1.0);
for (int i=-100; i<=100; i+=10)
{
glBegin(GL_LINES);
glVertex3f(i,0.0f,-100.0f);
glVertex3f(i,0.0f,100.0f);
glEnd();
glBegin(GL_LINES);
glVertex3f(-100.0f,0.0f,i);
glVertex3f(100.0f,0.0f,i);
glEnd();
}
glPopAttrib();
}

void Draw()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
DrawBox(box[0].x,box[0].y,box[0].z);
DrawBox(box[1].x,box[1].y,box[1].z);
DrawBox(box[2].x,box[2].y,box[2].z);
DrawGrid();
glutSwapBuffers();
}
void Update() { static int count; if (count >= 0) { box[0].y+=0.02; box[1].y+=0.04; box[2].y+=0.08; } else { box[0].y-=0.02; box[1].y-=0.04; box[2].y-=0.08; } count++; if (count == 100) count=-count; glLoadIdentity(); setLookAt(); glutPostRedisplay(); }void Reshape(int w,int h)
{
WinWidth=w;
WinHeight=h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0,0,w,h);
gluPerspective(45,1.0*w/h,1,1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

}
void init()
{
glClearColor(0.0,0.0,0.0,0.0);
glEnable(GL_DEPTH_TEST);
setAll(20,1.75,0,0,1.75,0,0,1,0);
boxTexture=LoadBitmap("Box.bmp");
box[0].x=-2.0;
box[0].y=0.5;
box[0].z=0.0;
box[1].x=0.0;
box[1].y=0.5;
box[1].z=0.0;
box[2].x=2.0;
box[2].y=0.5;
box[2].z=0.0;
}
void ProcessKeyboard(unsigned char key,int x,int y)
{
static double delta;
if (key == 'a')
{
delta+=0.03;
}
if (key == 'd')
{
delta-=0.03;
}
setPos(20*cos(delta),posY,20*sin(delta));
}
int main(int argc, char *argv[])
{
WinWidth=400;
WinHeight=400;
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE);
glutInitWindowPosition(100, 100);
glutInitWindowSize(WinWidth, WinHeight);
glutCreateWindow("HelloOpenGL");
glutReshapeFunc(&Reshape);
glutIdleFunc(&Update);
glutDisplayFunc(&Draw);

glutKeyboardFunc(&ProcessKeyboard);

init();
glutMainLoop();
return 0;
}


作者:plusplus7
日期:2013年3月1日
转载请注明出处
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: