本文共 4586 字,大约阅读时间需要 15 分钟。
由于接下来的实验要实现火柴人的动作,所以实验要求要采用分层设计,如下图所示:
这样转动hip(臀部),整个火柴人就整体转动。比如如果要动左腿,那么在相对hip上进行自己的操作,这样设计对火柴人的动作实现很方便。
贴上自己的代码,程序用递归来实现分层设计,此外还增添了火柴人旋转功能:
#define _STDCALL_SUPPORTED#includeGLUquadricObj *uquadric; //二次曲面声明类型void drawTorso();void drawLeftleg1();void drawRightleg1();void drawLeftarm1();void drawLefttarm2();void drawRightarm1();void drawRightarm2();void drawNeck();void drawHead();void selfRotateRL1();//画臀部,根节点void drawHip(){ glScalef(2.0,0.5,1.0); glPushMatrix(); glTranslatef(0.0,-1.0,0.0); glutWireCube(0.3); drawTorso(); drawLeftleg1(); drawRightleg1(); glPopMatrix();}//画肩膀void drawShoulder(){ glScalef(2.0,0.5,2.0); //先还原成1:1 glScalef(2.0,0.5,1.0); glPushMatrix(); glTranslatef(0.0,1.45,0.0); glutWireCube(0.4); drawRightarm1(); drawLeftarm1(); drawNeck(); drawHead(); glPopMatrix();}//画躯干void drawTorso(){ glScalef(0.5,2.0,1.0); //先还原成1:1 glScalef(0.5,2.0,0.5); //躯干Z轴方向缩短一半,不然躯干太粗 glPushMatrix(); glTranslatef(0.0,0.35,0.0); glutWireCube(0.6); drawShoulder(); glPopMatrix();}void drawRightarm2(){ glPushMatrix(); //差点忘记了,arm1是绕x轴旋转了90度,所以三维坐标也跟着旋转了90度 //这里第二个是“z轴”,负的往里,正的往外 //第三个是“y轴”,负的网上,正的往下 glTranslatef(0.0,0.0,0.7); glRotatef(15,0.0,-1.0,0.0); gluCylinder(uquadric, 0.08, 0.08, 0.6, 20.0, 8.0); glPopMatrix();}void drawRightarm1(){ glScalef(0.5,2.0,1.0); //还原成1:1 glPushMatrix(); //gluQuadricDrawStyle(uquadric, GLU_FILL); //控制绘图风格 glTranslatef(-0.3,-0.05,0.0); glRotatef(90,1.0,0.0,0.0); gluCylinder(uquadric, 0.08, 0.08, 0.7, 20.0, 8.0); drawRightarm2(); glPopMatrix();}void drawLeftarm2(){ glPushMatrix(); glTranslatef(0.0,0.0,0.7); glRotatef(15,0.0,1.0,0.0); gluCylinder(uquadric, 0.08, 0.08, 0.6, 20.0, 8.0); glPopMatrix();}void drawLeftarm1(){ glPushMatrix(); glTranslatef(0.3,-0.05,0.0); glRotatef(90,1.0,0.0,0.0); gluCylinder(uquadric, 0.08, 0.08, 0.7, 20.0, 8.0); drawLeftarm2(); glPopMatrix();}//画头void drawHead(){ glPushMatrix(); glTranslatef(0.0,0.65,0.0); glutWireCube(0.40); glPopMatrix();}//画脖子void drawNeck(){ glPushMatrix(); glTranslatef(0.0,0.40,0.0); glRotatef(90,1.0,0.0,0.0); gluCylinder(uquadric, 0.10, 0.10, 0.30, 20.0, 8.0); glPopMatrix();}void drawRightLeg2(){ glPushMatrix(); glTranslatef(0.0,0.0,0.8); //glRotatef(10,0.0,-1.0,0.0); gluCylinder(uquadric, 0.1, 0.1, 0.8, 20.0, 8.0); glPopMatrix();}void drawRightleg1(){ //glScalef(2.0,0.5,1.0); //先还原成1:1 glPushMatrix(); glTranslatef(0.20,-0.05,0.0); //注意这里坐标轴绕x旋转了90度,leg2的坐标会变化 glRotatef(90,1.0,0.0,0.0); gluCylinder(uquadric, 0.1, 0.1, 0.8, 20.0, 8.0); drawRightLeg2(); glPopMatrix();}void drawLeftLeg2(){ glPushMatrix(); glTranslatef(0.0,0.0,0.8); //glRotatef(10,0.0,-1.0,0.0); gluCylinder(uquadric, 0.1, 0.1, 0.8, 20.0, 8.0); glPopMatrix();}void drawLeftleg1(){ glScalef(2.0,0.5,1.0); //先还原成1:1 glPushMatrix(); glTranslatef(-0.20,-0.05,0.0); //注意这里坐标轴绕x旋转了90度,leg2的坐标会变化 glRotatef(90,1.0,0.0,0.0); gluCylinder(uquadric, 0.1, 0.1, 0.8, 20.0, 8.0); drawLeftLeg2(); glPopMatrix();}static float rotateAngle = 0;static int times1 = 0;void selfRotateWhole(){ times1++; if(times1 > 50) { times1 = 0; } if(times1 % 50 == 0) { rotateAngle += 0.5; } glRotatef(rotateAngle, 0, 1, 0); glRotatef(rotateAngle, 1, 0, 0);}//自由旋转转动void renderScene(){ glClear(GL_COLOR_BUFFER_BIT); //清除当前可写的颜色缓冲 glColor3f(1.0,0.0,0.0); glLoadIdentity(); gluLookAt(0.0,0.0,0.0,0.0,0.0,-1.0,0.0,1.0,0.0); glLoadIdentity(); /* glMatrixMode设置当前矩阵模式: GL_MODELVIEW,对模型视景矩阵堆栈应用随后的矩阵操作. GL_PROJECTION,对投影矩阵应用随后的矩阵操作. GL_TEXTURE,对纹理矩阵堆栈应用随后的矩阵操作. 与glLoadIdentity()一同使用 */ glMatrixMode(GL_MODELVIEW); glScalef(0.5,0.5,1.0); //先缩放下,不然木头人会很大。。。 glPushMatrix(); selfRotateWhole(); drawHip(); glPopMatrix(); glFlush(); //glutSwapBuffers();}void init(){ glClearColor(0.0,0.0,0.0,0.0); //glClearColor(R,G,B,AFA)清空当前颜色,并且设定颜色值 glShadeModel(GL_FLAT); //设置着色模式。 uquadric = gluNewQuadric();}int main(int argc, char *argv[]){ glutInit(&argc, argv); /* GLUT_RGB:指定 RGB 颜色模式的窗口 GLUT_SINGLE:指定单缓存窗口 */ glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); glutInitWindowPosition(100, 100); glutInitWindowSize(500, 500); glutCreateWindow("太空漂浮"); init(); //glutDisplayFunc(display); glutDisplayFunc(renderScene); glutIdleFunc(renderScene); //glutReshapeFunc(reshape); glutMainLoop(); return 0;}
附上几张运行图片: