这是我们计算机图形学的第二个project,刚刚接触计算机图形学,openGL什么都不懂,废了很长时间才如期交了项目。下面就将整个过程记录下来。
openGL是基于C语言的,我个人认为,它就是一个处理和玩耍图形的函数库。这些函数都是大牛们研究发明出来的,老师给我们讲texture讲了四节课,你使用的话只要几行代码就完成了。如果让我们写个texture映射的函数,或者写个光照函数,那就呵呵了。在此推荐一个openGL很火很有用的教程:
http://users.polytech.unice.fr/~buffa/cours/synthese_image/DOCS/Tutoriaux/Nehe/opengl.htm
这是英文的,不要怕,这只是用来装逼的,有人进行了原版翻译,就在下面:
http://www.yakergong.net/nehe/
熟悉熟悉openGL就开始干了,摸索摸索。
先看main()方法:
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
/* get a 640 x 480 window */
glutInitWindowSize(640, 480);
/* the window starts at the upper left corner of the screen */
glutInitWindowPosition(0, 0);
/* Open a window */
window = glutCreateWindow("STICK PERSON");
/* Register the function to do all our OpenGL drawing. */
glutDisplayFunc(&DrawGLScene);
/* Go fullscreen. This is as soon as possible. */
glutFullScreen();
/* Even if there are no events, redraw our gl scene. */
glutIdleFunc(&DrawGLScene);
/* Register the function called when our window is resized. */
glutReshapeFunc(&ReSizeGLScene);
/* Register the function called when the keyboard is pressed. */
glutKeyboardFunc(&keyPressed);
/* Initialize our window. */
InitGL(640, 480);
/* Start Event Processing Engine */
glutMainLoop();
return 1;
}
尽管每行都有注释,其实我一行也不懂。这些都是一个教程源码里的,main()方法大多是做了一些初始化。你的工作大部分都在DrawGLScense上,这个就是画的函数。我做这个实验的时候就是从一个教程上的源码改起,利用他的框架和初始化,我只在DrawGLScense()方法里活动。听上去比较猥琐,但是对于急着赶着交的同学还是比较实在的。下面介绍的就是DrawGLScense()方法:
void DrawGLScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-40.0f);
glRotatef(angle,0,1,0);
glPushMatrix();
glTranslatef(0.0f,0.0f,-20.0f);
glRotatef(-90,0,1,0);
glPushMatrix();
glTranslatef(0.0f,1.2f,0.0f);
glPushMatrix();
glTranslatef(0.8,0.0,0.0);
glTranslatef(0.0,-0.4,0.0);
glRotatef(angleoflarma,1,0,0);
glPushMatrix();
glTranslatef(0.0,-0.8,0.0);
glTranslatef(0.0,-0.4,0.0);
glRotatef(-90,1,0,0);
DrawArmA();
glPopMatrix();
DrawArmB();
glPopMatrix();
glPushMatrix();
glTranslatef(-0.8,0.0,0.0);
glTranslatef(0.0,-0.4,0.0);
glRotatef(angleofrarma,1,0,0);
glPushMatrix();
glTranslatef(0.0,-0.8,0.0);
glTranslatef(0.0,-0.4,0.0);
glRotatef(-90,1,0,0);
DrawArmA();
glPopMatrix();
DrawArmB();
glPopMatrix();
//return shoulder
glPushMatrix();
glTranslatef(0.0,0.3,0.0);
glPushMatrix();
glTranslatef(0.0,0.7,0.0);
DrawHead();
glPopMatrix();
DrawNick();
glPopMatrix();
DrawShoulder();
glPopMatrix();
//return body
glPushMatrix();
glTranslatef(0.0f,-1.2f,0.0f);
glPushMatrix();
glTranslatef(0.4,0.0,0.0);
glTranslatef(0.0,-0.4,0.0);
glRotatef(angleoflleg,1,0,0);
DrawLeg();
glPopMatrix();
glPushMatrix();
glTranslatef(-0.4,0.0,0.0);
glTranslatef(0.0,-0.4,0.0);
glRotatef(angleofrleg,1,0,0);
DrawLeg();
glPopMatrix();
DrawWaise();
glPopMatrix();
DrawBody();
glPopMatrix();
glPopMatrix();
angleoflarma += a;
angleofrarma -= a;
angleoflleg -= b;
angleofrleg += b;
angle += 0.1;
if(angleoflarma > 50){
a = -1.0;
b = -0.5;
}
if(angleoflarma < -50){
a = 1.0;
b = 0.5;
}
glutSwapBuffers();
}
/* The function called whenever a key is pressed. */
void keyPressed(unsigned char key, int x, int y)
{
/* avoid thrashing this procedure */
usleep(100);
/* If escape is pressed, kill everything. */
if (key == ESCAPE)
{
/* shut down our window */
glutDestroyWindow(window);
/* exit the program...normal termination. */
exit(0);
}
}
这是有点长,让我理一理,因为我们要画成一个木头人,必然有胳膊有腿,而且是三维的。代码中drawBody(),drawArm()等方法就是画长方体的。现在该说一下画的流程了。在此之前还应该说一下glPopMatrix()和glPushMatrix(),因为人是有关节的。小胳膊活动的时候必须以大胳膊的下面为中心,而大胳膊又得以肩膀为中心。这听上去很复杂,当大胳膊动了,小胳膊咋办?这时就得靠层次来解决了。pop和push就是来体现层次的。
我们先调整一下当前的原点,
glLoadIdentity();
将原点置于屏幕中央。为了便于小人转圈活动,
glTranslatef(0.0f,0.0f,-40.0f);
glRotatef(angl