首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 编程语言 > C/C++ > OpenGL的视图变换
【标  题】:OpenGL的视图变换
【关键字】:OpenGL
【来  源】:http://www.cppblog.com/bch515/archive/2006/08/11/11142.html

OpenGL的视图变换

C++博客 - The Coder - OpenGL的视图变换

The Coder

I am a humble coder.

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  4 随笔 :: 4 文章 :: 1 评论 :: 0 Trackbacks

OpenGL 中场景进行变换,要经历一些过程:视图变换 à 模型变换 à 投影变换,然后到了窗口坐标。这几个变换开始的时候把我搞很混,这几天整理一下。

?????? 一般书上把这几个变换用照相机类比,其实每个变换都是产生着一个 4x4 矩阵,然后与当前矩阵 (Current Matrix) 相乘,得到一个坐标变换矩阵,最后把世界坐标系(欧式空间)中的物体变换到屏幕坐标系中。这里梳理一下概念:

?????? 1 、视图变换( VIEW Transformation ):它类似将照相机指向物体,即确定视点(观察点)的位置和观察方向。一般用的函数为 glu 封装的函数:

void gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez,? --------- 观察点

?????? GLdouble centrex, GLdouble centrey, GLdouble centrez,? -- 视线方向:从 eye 指向 centre

?????? GLdouble upx, GLdouble upy, GLdouble upz ------------ 视图体自下而上的方向

?)

?????? 这个函数会产生一个视图矩阵,并右乘到当前矩阵上。模型变换通常发生在模型变换之前。其实,视图变换也是通过平移和旋转得到的,观察位置与物体位置之间是个相对的状态,我们也把视图变换和模型变换统一成一个变换,产生一个矩阵:模型视图变换矩阵。

?????? 2 、模型变换 (MODEL Transformation) :它确定模型的位置和方向,对模型进行旋转、平移和缩放。用到三个子函数: glTranslate*(x, y, z) glRotate*(x, y, z) glScale*(x, y, z) 。每个函数都会产生一个矩阵,并右乘当前矩阵。

?????? 3 、投影变换( PROJECTION Transformation ):产生一个六面的视图体,把视图体以外的场景剪裁掉,把视图体内的物体、场景作为绘制对象,让“照相机拍摄”。两种投影方式,两个投影函数: glFrustum(left, right, bottom, top, near, far)

glOrtho(left, right, bottom, top, near, far )

这两个函数的参数非常对称,都是构筑了一个六面体,形成可视范围。它们都产生一个矩阵,并左乘当前矩阵。(当然,还有 glu 的两个函数)。

??????

?????? 要理解整个过程,关键在理解当前变换矩阵 CTM ,(简称为 C )。它是一个状态概念,应用到 OpenGL 流水线中的每一个定点: P = C*P’ 。这条等式是对同一个点在两个坐标系体统之间进行转换,从右边的坐标系下的坐标( P’ )转换到左边的坐标系下的坐标( P )。而矩阵 C 4x4 的齐次坐标矩阵,它都蕴含着一个局部坐标系信息:以右边坐标系为参考坐标系统,左边坐标系的位置和方向。

?????? 用手工定义一个矩阵,如下(按 OpenGL 矩阵方式定义。与数学定义矩阵的方式转置):

?????? CTM[16] = { a0, a1, a2, a3,???????? // x 轴的方向向量

???????????????????? ?? a4, a5, a6, a7,????????? // y 轴的方向向量

???????????????????? ?? a8, a9, a10, a11,????????????? // z 轴的方向向量

???????????????????? ?? a12, a13, a14, a15??? // 原点的位置

??????????????????????????? }

??????

?????? 再来考察当前变换矩阵 CTM ,它是在 OpenGL 流水线中一个模型视图矩阵和一个投影矩阵的复合。 CTM = P*C*M 。(注意到上面提到的左乘右乘了吗?)
?aa.bmp

我们来分析一个简单的例子: 

?

?

?1 #define ?NUM?0.70710678118654746
?2 // 注意这个矩阵是正交的,没有正交就用,好像有放缩作用
?3 GLfloat?Tmat[ 16 ]? = ? {?NUM,?NUM,? 0.0 ,? 0.0 ,???????????????? // ?x?axis
?4 ???????????????????? - NUM,?NUM,? 0.0 ,? 0.0 ,???????????? // ?y?axis  
?5 ????????????????????? 0.0 ,? 0.0 ,? 1.0 ,? 0.0 ,???????????????? // ?z?axis
?6 ????????????????????? 3.0 ,? 3.0 ,? 0.0 ,? 1.0 }
;???????????????? // ?origin????
?7 void ?setupRC( void )
?8 {
?9 ????glClearColor( 0.0f ,? 0.0f ,? 0.0f ,? 1.0f );
10 ????glShadeModel(GL_FLAT);
11 }

12
13 void ?RenderScene( void )
14 {
15 ????printf( " RenderScene\n " );??
16 glClear(GL_COLOR_BUFFER_BIT);
17 glColor3f( 0.0f ,? 1.0f ,? 1.0f );
18 ????glMatrixMode(GL_MODELVIEW);
19 ????glLoadIdentity();
20 ????gluLookAt( 0.0 ,? 0.0 ,? 5.0 ,???????? // ?view?point
21 ?????????????? 0.0 ,? 0.0 ,? 0.0 ,???????? // ?focus?point
22 ?????????????? 0.0 ,? 1.0 ,? 0.0 );??????? // ?up?vector
23
24 ? ?glutSolidCube( 0.5 );???????????????? //  原点的参考位置
25 ????glMultMatrixf(Tmatr);???????????????? // 这个矩阵的动作和下面的两个变换是一样的。
26 // ????glRotatef(45.0,?0.0,?0.0,?1.0);
27 // ????glTranslatef(3.0,?0.0,?0.0);
28 ????glutSolidCube( 1.0 );
29
30 ????glutSwapBuffers();
31 }

32
33 void ?ChangeSize( int ?w,? int ?h)
34 {
35 ????printf( " ChangeSize\n " );??? // 从这里看出,是先调用ChangeSize()的
36 ????GLfloat?nRange? = ? 10.0f ;
37
38 ???? if (h? == ? 0 )
39 ????????h? = ? 1 ;
40 ????GLfloat?fRatio? = ?(GLfloat)w? / ?(GLfloat)h;
41
42 ????glMatrixMode(GL_PROJECTION);
43 ????glLoadIdentity();
44
45 ???? if (w? <= ?h)
46 ????????glOrtho( - nRange,?nRange,? - nRange? / ?fRatio,?nRange? / ?fRatio,? 1.0 ,?nRange);
47 ???? else
48 ????????glOrtho( - nRange? * ?fRatio,?nRange? * ?fRatio,? - nRange,?nRange,? 1.0 ,?nRange);
49
50 ????glViewport( 0 ,? 0 ,?w?,h);
51
52 ????glMatrixMode(GL_MODELVIEW);
53 ????glLoadIdentity();
54 }

55
56 int ?main( int ?argc,? char * ?argv[])
57 {
58 ????glutInit( & argc,?argv);
59 ????glutInitDisplayMode(GLUT_RGB? | ?GLUT_DOUBLE);
60 ????glutInitWindowSize( 800 ,? 600 );
61 ????glutCreateWindow( " example " );
62
63 ????glutReshapeFunc(ChangeSize);
64 ????glutDisplayFunc(RenderScene);
65
66 ????setupRC();
67
68 ????glutMainLoop();
69
70 ????std::cout? << ? " Hello?world! " ? << ?std::endl;
71 ???? return ? 0 ;
72 }

73

glRotatef(45.0, 0.0, 0.0, 1.0)???

glTranslatef(3.0, 0.0, 0.0);  

这两个变换,可以看成:

?????? glMultMatrixf(R);

?????? glMultMatrixf(T);

R,T 都是右乘到 CTM CTM = CTM * R * T

对模型变换的理解有两种:

1、在全局固定坐标系下,对物体进行变换。这时候,我们要以相反的顺序来考虑代码中的变换函数了,它的实际过程是这样 P = CTM *( R*(T* p’))

首先、对物体进行平移,平移到坐标( 3.0, 0.0, 0.0 )。  然后,把物体相对原点绕z轴旋转45度。

2、物体捆绑在局部坐标系下,所有的变换都是坐标系进行的。这时,我们用顺序来看这个变换。

glRotatef(45.0, 0.0, 0.0, 1.0) 产生一个齐次矩阵 R( 这可是代表一个局部坐标系哦 ) ? ,即局部坐标系 R 相对刚才开始的坐标系 I (单位矩阵)作了旋转变换,绕旋转了45度。

glTranslatef(3.0, 0.0, 0.0) 产生一个齐次矩阵 T (也是代表了一个局部坐标系),相对 R 坐标系沿x轴( R 系)平移了3个单位,得到了自己的局部坐标系 T

最后在这个局部坐标系 T 下画了 Cube

代码中的 Tmat = R * T ,它也是从 T 坐标系变换到 R 坐标系,再变换到最后的模型视图的世界坐标系。

?

?

后注:

?????? 对坐标系的几何变换是 既采用基于齐次坐标的矩阵表达形式 ! 又在欧氏几何的 Cartesian 坐标系下以对其进行说明性的定义 . 由于齐次坐标是射影几何的语言工具 ! 前者表明几何变换的表达是基于射影几何的后者则带有欧氏几何色彩 ,所以对它的表述清晰统一的表述比较难。本文写的也比较零散,有语焉不详、理解错误指出,请多多指正!

?

posted on 2006-08-11 22:27 TH 阅读(16) 评论(0)  编辑 收藏 收藏至365Key
文件或文件夹拷贝(源代码):【上一篇】
常见设计模式的解析和实现(C++)之二十一-完结篇:【下一篇】
【相关文章】
  • SUSE ATI OpenGL Video Driver Installation
  • OPENGL中3DMAX模型的应用
  • 窥视之窗-OpenGL中简单的Alpha实现。
  • 他山之玉 NEHE OPENGL教程第12章 翻译:cnscom
  • 学OpenGL编3D游戏(含全部源程序),讲述3D游戏的编写方法。
  • 不是读后感的读后感----NEHE的OPENGL教程
  • 用lex将xpm文件转换成为自定义的OpenGL使用的纹理文件格式
  • OpenGL中多边型网格化--环绕规则
  • Window OpenGL 程序C++版本
  • Java Bindings for OpenGL 1 - JOGL简介与安装
  • 【随机文章】
  • Linux内核编译全过程详解(kernel2.6.7)[转]
  • GIS开发随笔(2)——关于建立GIS数据库的几个问题
  • 关于div/idiv/mul/imul指令的用法
  • Response.ContentType 所有类型
  • WinRAR 也同样可以能管理我的桌面
  • Windows下的高级动画技术浅析
  • 用ACE静态服务配置实现简单的Echo服务
  • 一些有用的信息
  • 二叉树操作(C++版)
  • 如何写“完”UI设计说明书
  • 【相关评论】
    没有相关评论
    【发表评论】
    姓名:
    邮件:
    随机码*
    评论*
          
    |  首 页  |  版权声明  |  联系我们   |  网站地图  |
    CopyRight © 2004-2007 软讯网络 All Rigths Reserved.