高级计算机图形学 讲授 : 董兰芳研究方向 : 科学计算可视化图形 图像处理模式识别 Telephone:0551-3603484 Email:lfdong@ustc.edu.cn Homepage: http://staff.ustc.edu.cn/~lfdong 中国科学技术大学视觉计算与可视化实验室 1
第四章几何对象和变换 (3)( 4.9 变换的级联 4.10 OpenGL 变换矩阵 4.11 三维应用程序的接口 2
4.9 变换的级联 q=cbap=(c(b(ap))) q=mp 3
4.9.1 不动点在任意位置的旋转 M=T(P f )R(θ)T( )T(-P f ) 4
4.9.2 一般的旋转 以原点为不动点的旋转 R=R x R y R z 5
4.9.3 实例变换 实例的变换 M=TRS 6
4.9.4 绕任意轴的旋转 绕 z 轴 绕 x 轴 绕 y 轴 7
4.9.4 绕任意轴的旋转 绕任意轴旋转 y V=P 2 -P 1 =(x 2 -x 1,y 2 -y 1,z 2 -z 1 ) u P 2 P 1 x z 8
4.9.4 绕任意轴的旋转 将旋转轴正方向变换到 z 轴正方向的三个步骤 : 1. 将点 P 1 平移到坐标原点 y u x z 9
4.9.4 绕任意轴的旋转 U u 10
4.9.4 绕任意轴的旋转 2) 绕 x 轴旋转, 将向量 u 变换到 zx 平面上, 旋转的角度即为 u 和 z 的夹角 单位方向向量 u 在 yz 平面上的投影 u =(0,b,c) 11
4.9.4 绕任意轴的旋转 3). 绕 y 轴旋转, 将单位向量 u 变换到 z 轴正方向 设绕 y 轴旋转的角度为 β, 它 y 是 u 与 z 轴方向单位向量 u z 之 间的夹角, 那么有 u z =(0,0,1) u''=(a,0,d) x z 12
4.9.4 绕任意轴的旋转 在三维空间中绕任意轴做旋转变换的步骤来解决 : 1 将旋转轴正方向变换到 z 轴正方向, 变换矩阵为 R y (β)r x (α)t(-x 1,-y 1,-z 1 ); 2 绕 z 轴旋转角度 θ. 3 用 1 的逆变换将旋转轴变换回原来位置, 变换矩阵为 T(x 1,y 1,z 1 )R x (α) T R y (β) T 总结 : 复合变换矩阵的形式为 R(θ)=T(x 1,y 1,z 1 ) R x (α) T R y (β) T R z (θ) R y (β) R x (α) T(-x 1,-y 1,-z 1 ) 13
第四章几何对象和变换 (3)( 4.9 变换的级联 4.10 OpenGL 变换矩阵 4.11 三维应用程序的接口 4.12 四元数 14
4.10 OpenGL 变换矩阵 当前变换矩阵 : 15
4.10 OpenGL 变换矩阵 旋转 平移和缩放 : glrotatef(angle,vx,vy,vz); gltranslatef(dx,dy,dz); glscalef(sx,sy,sz); glloadmatrixf(pointer_to_matrix); glloadidentity(); 16
4.10 OpenGL 变换矩阵 在 OpenGL 中实现具有任意不动点的旋转 : glmatrixmode(gl_modelview); glloadidentity(); gltranslatef(4.0,5.0,6.0); glrotatef(45.0,1.0,2.0,3.0); gltranslatef(-4.0,-5.0,-6.0); 17
4.10 OpenGL 变换矩阵 变换的顺序 : C<-I C<-CT(4.0,5.0,6.0) C<-CR(45.0,1.0,2.0,3.0) C<-CT(-4.0,-5.0,-6.0) C=T(4.0,5.0,6.0)R(45.0,1.0,2.0,3.0) T(-4.0,-5.0,-6.0) 18
4.10 OpenGL 变换矩阵 立方体的旋转 : glutdisplayfunc(display); glutidlefunc(spincube); glutmousefunc(mouse); void spincube() { theta[axis] += 2.0; if( theta[axis] > 360.0 ) theta[axis] -= 360.0; glutpostredisplay(); } void display(void) { glclear(gl_color_buffer_bit GL_DEPTH_BUFFER_BIT); glloadidentity(); glulookat(1.0,1.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0); gltranslatef(0.0, 3.0, 0.0); glrotatef(theta[0], 1.0, 0.0, 0.0); glrotatef(theta[1], 0.0, 1.0, 0.0); glrotatef(theta[2], 0.0, 0.0, 1.0); glcolorpointer(3,gl_float, 0, colors); gldrawelements(gl_quads, 24, GL_UNSIGNED_BYTE, cubeindices); glutswapbuffers(); } 19
4.10 OpenGL 变换矩阵 立方体的旋转变换矩阵的加载 进栈和出栈 : glloadmatrixf(myarray) glmultmatrixf(myarray) Glfloat m[4][4]; Glfloat myarray[16]; glpushmatrix(); gltranslatef( ); gltranslatef( ); gltranslatef( ); glpopmatrix(); for(i=0;i<3;i++) for(j=0;j<3;j++) myarray[4*j+i]=m[i][j]; 20
第四章几何对象和变换 (3)( 4.9 变换的级联 4.10 OpenGL 变换矩阵 4.11 虚拟跟踪球 21
4.11 虚拟跟踪球 22
4.11 虚拟跟踪球 int float bool bool bool winwidth, winheight; angle = 0.0, axis[3], trans[3]; trackingmouse = false; redrawcontinue = false; trackballmove = false; main(int argc, char **argv) { glutinit(&argc, argv); glutinitdisplaymode(glut_double GLUT_RGB GLUT_DEPTH); glutinitwindowsize(500, 500); glutcreatewindow("colorcube"); glutreshapefunc(myreshape); glutdisplayfunc(display); glutidlefunc(spincube); glutmousefunc(mousebutton); glutmotionfunc(mousemotion); glenable(gl_depth_test); glmatrixmode(gl_projection); glloadidentity(); glortho(-2.0, 2.0, -2.0, 2.0, -2.0, 2.0); glmatrixmode(gl_modelview); glutmainloop(); } 23
4.11 虚拟跟踪球 void display(void) { glclear(gl_color_buffer_bit GL_DEPTH_BUFFER_BIT); /* view transform */ //glpushmatrix(); if (trackballmove) { glrotatef(angle, axis[0], axis[1], axis[2]); } colorcube(); //glpopmatrix(); glutswapbuffers(); } void mousebutton(int button, int state, int x, int y) { if(button==glut_right_button) exit(0); if(button==glut_left_button) switch(state) { case GLUT_DOWN: y=winheight-y; startmotion( x,y); break; case GLUT_UP: stopmotion( x,y); break; } } 24
4.11 虚拟跟踪球 startmotion(int x, int y) { } trackingmouse = true; redrawcontinue = false; startx = x; starty = y; curx = x; cury = y; trackball_ptov(x, y, winwidth, winheight, lastpos); trackballmove=true; stopmotion(int x, int y) { trackingmouse = false; if (startx!= x starty!= y) { redrawcontinue = true; } else { angle = 0.0F; redrawcontinue = false; trackballmove = false; } } 25
4.11 虚拟跟踪球 mousemotion(int x, int y) { float curpos[3], dx, dy, dz; trackball_ptov(x, y, winwidth, winheight, curpos); if(trackingmouse) {dx = curpos[0] - lastpos[0]; dy = curpos[1] - lastpos[1]; dz = curpos[2] - lastpos[2]; if (dx dy dz) { angle = 90.0F * sqrt(dx*dx + dy*dy + dz*dz); axis[0] = lastpos[1]*curpos[2] - lastpos[2]*curpos[1]; axis[1] = lastpos[2]*curpos[0] - lastpos[0]*curpos[2]; axis[2] = lastpos[0]*curpos[1] - lastpos[1]*curpos[0]; lastpos[0] = curpos[0]; lastpos[1] = curpos[1]; lastpos[2] = curpos[2]; }} glutpostredisplay();} 26
4.11 虚拟跟踪球 trackball_ptov(int x, int y, int width, int height, float v[3]) { float d, a; /* project x,y onto a hemi-sphere centered within width, height */ v[0] = (2.0F*x - width) / width; v[1] = (height - 2.0F*y) / height; d = (float) sqrt(v[0]*v[0] + v[1]*v[1]); v[2] = (float) cos((m_pi/2.0f) * ((d < 1.0F)? d : 1.0F)); a = 1.0F / (float) sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); v[0] *= a; v[1] *= a; v[2] *= a; } 27
第四章几何对象和变换 (3)( 4.9 变换的级联 4.10 OpenGL 变换矩阵 4.11 虚拟跟踪球 28