Win32 OpenGL编程(9) 投影变换

write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie

讨论新闻组及文件

提要

在前文(系列文章(7),以下简称XO7,系列其他文章类似)中的照相机比喻中提到了4种3D变换,如下:

1.确定照相机的位置的过程对应于“视图变换”(Viewing Transformations)

2.确定物体位置的过程对应于“模型变换”(Modeling Transformations)

3.确定照相机放大倍数的过程对应于“投影变换”(Projection Transformations)

4.确定照片大小的过程对应于“视口变换”(Viewport Transformations)

XO7中我们讲的是第一种变换视图变换,即改变观察者本身的位置,视角等的变换效果,XO8中讲的是第二种变换模型变换,本文开始继续按顺序讲解下一个3D变换过程,投影变换。

正投影

投影变换的过程就像是照相机选镜头的过程,目的是确定视野,其实说起来投影一词,我在学习工程制图的时候就接触过了,不知道大家是否学过这门课程,工程制图就是一种将三维空间的事物设想投影在二维空间中,然后画下来,工程中应用非常广泛,那时候学的那些剖面图什么的,也是累死我了-_-!OpenGL就可以模拟这样的过程,并且名字和工程制图中的名字是一样的,叫正投影。

OpenGL以glOrtho来指定一个正交平行的矩形,屏幕上显示的就是此物体在此矩形的正面的投影。在XO2中用过的gluOrtho2D实际上是此函数的一个去掉Z轴坐标的简化版,而glOrtho包括的参数nearVal,farVal表示此矩形的前,后两面,超出此矩形范围的图形将会被裁掉。

《OpenGL Programming Guide 》:

glOrtho — multiply the current matrix with an orthographic matrix
C Specification
void glOrtho( GLdouble left,
GLdouble right,
GLdouble bottom,
GLdouble top,
GLdouble nearVal,
GLdouble farVal);
Parameters

left, right

Specify the coordinates for the left and right vertical clipping planes.
bottom, top

Specify the coordinates for the bottom and top horizontal clipping planes.
nearVal, farVal

Specify the distances to the nearer and farther depth clipping planes.
These values are negative if the plane is to be behind the viewer.

用此函数,通过调整nearVal与farVal我们可以实现类似工程制图中的剖面的效果,见下例:

GLfloat gfNear = 1.0;//这里进行所有的绘图工作
voidSceneShow(GLvoid)
{glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0, 0.0, 0.0);

glMatrixMode(GL_PROJECTION);glLoadIdentity();glOrtho(-1.0, 1.0, -1.0, 1.0, gfNear, -1.0);

glPushMatrix();DrawSmoothColorPyramid(0.5);glPopMatrix();

glFlush();
}  

///

intGame_Main(void*parms = NULL, intnum_parms = 0)
{DWORD dwStartTime;

dwStartTime = GetTickCount();// this is the main loop of the game, do all your processing
// here

// for now test if user is hitting ESC and send WM_CLOSE
if(KEYDOWN(VK_ESCAPE))SendMessage(ghWnd,WM_CLOSE,0,0);

if(KEYDOWN(VK_UP)){gfNear -= 0.01;}

if(KEYDOWN(VK_DOWN)){gfNear += 0.01;}

SceneShow();

// 控制帧率
while
(GetTickCount() - dwStartTime < TIME_IN_FRAME){Sleep(1);}

// return success or failure or your own return code here
return
(1);

} // end Game_Main
以下就是当nearVal为0.8时的效果,也就是说,Z轴坐标大于0.8的,一律被截掉了,在工程制图中,我们老师常将,此时假设在此用一刀将物体切掉。
上面的源代码中还出现了一个新函数,glMatrixmode,用于指定以下的变换是针对哪个变换的,

glMatrixMode(GL_PROJECTION);

用于指定以下的变换是针对投影变换的,而用
glMatrixMode(GL_MODELVIEW);
方式调用时,(默认值)表示 针对模型变换。
为节省篇幅仅贴出关键片段,完整源代码见我博客源代码的2008-10-28/glOrthoSample 目录,获取方式见文章最后关于获取博客完整源代码的说明。

透视投影

上述的正投影仅仅存在于想象之中,主要是工程制图(或者CAD)中能够正确反映物体的真实尺寸,现实中我们看东西,越远的越小,越近的越大,并且所有物体最终会消失在远方(地平线),OpenGL常用于VR(虚拟现实),这样程度的视觉仿真效果自然是有的,在OpenGL中,这样投影叫做透视投影。OpenGL提供了两个函数用于指定透视投影,两个函数仅仅是参数表示的方式不同,事实上效果是一样的。

《OpenGL Programming Guide 》:

glFrustum — multiply the current matrix by a perspective matrix
C Specification
void glFrustum( GLdouble left,
GLdouble right,
GLdouble bottom,
GLdouble top,
GLdouble nearVal,
GLdouble farVal);
Parameters

left, right

Specify the coordinates for the left and right vertical clipping planes.
bottom, top

Specify the coordinates for the bottom and top horizontal clipping planes.
nearVal, farVal

Specify the distances to the near and far depth clipping planes.
Both distances must be positive.

gluPerspective — set up a perspective projection matrix
C Specification
void gluPerspective( GLdouble fovy,
GLdouble aspect,
GLdouble zNear,
GLdouble zFar);
Parameters

fovy

Specifies the field of view angle, in degrees, in the y direction.
aspect

Specifies the aspect ratio that determines
the field of view in the x direction.
The aspect ratio is the ratio of x (width) to y (height).
zNear

Specifies the distance from the viewer to the near clipping plane
(always positive).
zFar

Specifies the distance from the viewer to the far clipping plane
(always positive).

事实上,glFrustum指定的方式与glOrtho很像,参数意义也一致,仅仅是使用后OpenGL使用的投影方式不同,gluPerspective函数指定的方式是模拟观察者(照相机)的视角,用fovy指定观察者的上下视角(及在y-z平面上观察的角度),aspect指定观察宽度与高度的比,然后用zNear指定离观察者较近的截面,用zFar指定离观察者较远的截面(都指离观察者的距离),下例展示了原来那个三角锥从远方的一个小点然后到放大到原来大小的过程:

GLfloat gfDis = 5.0;

//这里进行所有的绘图工作
voidSceneShow(GLvoid)
{glMatrixMode(GL_PROJECTION);glLoadIdentity();glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 5.0);

glMatrixMode(GL_MODELVIEW);glLoadIdentity();gluLookAt(0.0, 0.0, gfDis, 0.0, 0.0, -1.0, 0.0, 1.0, 0.0);

glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0, 0.0, 0.0);

glPushMatrix();DrawSmoothColorPyramid(0.5);glPopMatrix();

glFlush();
}  

intGame_Main(void*parms = NULL, intnum_parms = 0)
{DWORD dwStartTime;

dwStartTime = GetTickCount();// this is the main loop of the game, do all your processing
// here

// for now test if user is hitting ESC and send WM_CLOSE
if(KEYDOWN(VK_ESCAPE))SendMessage(ghWnd,WM_CLOSE,0,0);

if(KEYDOWN(VK_UP)){gfDis -= 0.01f;}

if(KEYDOWN(VK_DOWN)){gfDis += 0.01f;}

SceneShow();

// 控制帧率
while
(GetTickCount() - dwStartTime < TIME_IN_FRAME){Sleep(1);}

// return success or failure or your own return code here
return
(1);

} // end Game_Main
上面例子中靠

gluLookAt(0.0, 0.0, gfDis, 0.0, 0.0, -1.0, 0.0, 1.0, 0.0);

来调整观察者的位置,通过上下键调节,会模拟出一种慢慢走近三角锥的过程,三角锥也是随着走近由小慢慢变大。

实际上最重要的还是

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 5.0);

三句确定的透视投影方式。

为节省篇幅仅贴出关键片段,完整源代码见我博客源代码的2008-10-28/glPerspective 目录,获取方式见文章最后关于获取博客完整源代码的说明。

小结:

相对来说,个人认为投影变换是属于OpenGL中重要但是确较难理解的一部分,动态变化上述函数的参数,准确理解上述函数中每个参数的意义是种不错的学习途径,其中Nate Robin的OpenGL教程有个很形象的教学程序,推荐给大家(实际上为《OpenGL Programming Guide 》中推荐的),http://www.xmission.com/~nate/tutors.html 中有下载的。对应投影变换的教程为projection一例。

参考资料

1. 《OpenGL Reference Manual 》,OpenGL参考手册

2. 《OpenGL 编程指南》(《OpenGL Programming Guide 》),Dave Shreiner,Mason Woo,Jackie Neider,Tom Davis 著,徐波译,机械工业出版社

3. 《Nehe OpenGL Tutorials》,Nehe著,在http://nehe.gamedev.net/ 上可以找到教程及相关的代码下载,(有PDF版本教程下载)Nehe自己还做了一个面向对象的框架,作为演示程序来说,这样的框架非常合适。也有中文版 ,各取所需吧。

4. 《OpenGL入门学习》 ,eastcowboy著,这是我在网上找到的一个比较好的教程,较为完善,而且非常通俗。这是第一篇的地址:http://bbs.pfan.cn/post-184355.html

本OpenGL系列其他文章

1. 《 Win32 OpenGL 编程(1)Win32下的OpenGL编程必须步骤 》

2. 《Win32 OpenGL编程(2) 寻找缺失的OpenGL函数 》

3. 《Win32 OpenGL编程(3) 基本图元(点,直线,多边形)的绘制 》

4. 《Win32 OpenGL编程(4) 2D图形基础(颜色及坐标体系进阶知识) 》

5. 《Win32 OpenGL编程(5)顶点数组详细介绍 》

6.《Win32 OpenGL编程(6) 踏入3D世界 》

7.《Win32 OpenGL编程(7) 3D视图变换——真3D的关键 》

8.《Win32 OpenGL编程(8) 3D模型变换及其组合应用 》

应用举例:《Win32 OpenGL编程系列 2D例子 -- 七巧板图形绘制 》

完整源代码获取说明

由于篇幅限制,本文一般仅贴出代码的主要关心的部分,代码带工程(或者makefile)完整版(如果有的话)都能用Mercurial在Google Code中下载。文章以博文发表的日期分目录存放,请直接使用Mercurial克隆下库:

https://blog-sample-code.jtianling.googlecode.com/hg/

Mercurial使用方法见《分布式的,新一代版本控制系统Mercurial的介绍及简要入门 》

要是仅仅想浏览全部代码也可以直接到google code上去看,在下面的地址:

http://code.google.com/p/jtianling/source/browse?repo=blog-sample-code

原创文章作者保留版权 转载请注明原作者 并给出链接

write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie

Win32 OpenGL编程(9) 投影变换相关推荐

  1. Win32 OpenGL 编程(1)Win32下的OpenGL编程必须步骤

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! Win3 ...

  2. Win32 OpenGL 编程

    Win32 OpenGL 编程(1)Win32下的OpenGL编程必须步骤 一.    前言 人生在于折腾,继续折腾吧. OpenGL 编程的红宝书< OpenGL Programming Gu ...

  3. Win32 OpenGL编程 5 顶点数组详细介绍

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! Win3 ...

  4. Win32 OpenGL编程系列 2D例子 -- 七巧板图形绘制

    write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie 讨论新闻组及文件 OpenGL系列文章都已经写到3D部分了,但是感觉2D的例子还是少了点,特意弄个外 ...

  5. Win32 OpenGL编程(4) 2D图形基础(颜色及坐标体系进阶知识)

    Win32 OpenGL 编程 (4) 2D 图形基础(颜色及坐标体系进阶知识) write by 九天雁翎 (JTianLing) -- blog.csdn.net/vagrxie 讨论新闻组及文件 ...

  6. Qt下的OpenGL 编程(3)绘制平面几何体

    一. 提要 之前的一篇教程已经搭建好了Qt下的OpenGL的编程环境,几天要来学习的就是OpenGL的2D绘图. 2D作为绘图的基础,还是很值得去好好学习,比如迪卡尔坐标,透视设置等等,而所谓的3D, ...

  7. OpenGL编程入门学习

    OpenGL编程入门学习  非常详细的教程,很适合初学者 本文转自:http://www.cppblog.com/doing5552/archive/2009/01/08/71532.html === ...

  8. OpenGL编程指南7:视图-

    1.前言 计算机图形学的要点就是创建三维物体的二维图像(图像必须是二维的,因为他是在平面的屏幕上显示的).但是,当我们决定怎样在屏幕上绘图时,必须使用三维坐标的方式考虑. 为了把一个物体的三维坐标变成 ...

  9. OpenGL编程轻松入门(一)

    OpenGL编程轻松入门(一) (由同事黄燕创作)   本文介绍了有关OpenGL的基本知识,主要涉及颜色.绘制几何体.坐标变换.堆栈操作.显示列表.光照和材质.纹理映射.特殊效果.曲面和曲线的绘制. ...

最新文章

  1. Custom Client Side Drag and Drop Behavior in ASP.NET AJAX
  2. 小米履带机器人充电时一直响_小米有品上线擦地机器人,每天放出去溜一圈,老婆夸我家务做的好...
  3. [总结]Asp.net中的页面乱码的问题
  4. Machine Learning week 3 quiz : Regularization
  5. 科大星云诗社动态20220115
  6. Signalr2_消息弹窗
  7. 神经网络模型遇到瓶颈?这些Tricks让你相见恨晚!
  8. 实现织梦dedecms百度主动推送(实时)网页抓取
  9. python dict hash_Python Hashmap/Dicti
  10. python3读取多行数据合并_python3 数据规整化:清理、转换、合并、重塑(一)
  11. “物联网开发实战”学习笔记-(一)硬件开发环境的搭建
  12. 神州十二号载人飞船和空间站对接成功 我们的目标是星辰大海!
  13. 指南针经纬度分秒格式转换10进制经纬度
  14. aspose利用word模板生成word、PDF
  15. e8 c 虚拟服务器,电信光猫e8-c怎么设置拨号方式上网
  16. macOS:实现 声音内录 不用其它App
  17. TortoiseSVN安装及导入已有SVN仓库
  18. RT-Thread Env工具下 scons命令构建工程 SConscript和Kconfig修改示例
  19. 静态库与动态库之间的区别
  20. 冯诺依曼体系结构+操作系统

热门文章

  1. aelf主网启动路线图正式发布
  2. uniapp禁止屏幕滚动
  3. 光功率计制作-给大家参考 资料分享
  4. 2、编译、交叉编译概念小记
  5. struts标签html:select,JSP_Struts标签 htmlselect option基本用法.doc
  6. 浙江省主要农作物种植面积和总产量数据
  7. 计算机毕业设计SSM服装销售商城系统【附源码数据库】
  8. 记录手贱修改win10 msconfig导致开机蓝屏解决方法
  9. linux使用quercus在tomcat环境中运行php程序
  10. 全志平台MIPI屏调试记录