[转]gluProject 和 gluUnproject 的详解
gluProject 和 gluUnproject 的详解
简介:
三维空间中,经常需要将 3D 空间中的点转换到 2D(屏幕坐标),或者将 2D 点转换到 3D 空间中。当你使用 OpenGL 的时候,简单使用 gluProject() 和 gluUnproject() 函数就可以实现这个功能了。但这两个神奇的函数是怎样实现的,一直困扰着我,经过一番仔细研究,将自己的思路写在这里:
gluPorject()
先通过看代码,来一步一步分析它的数学原理吧!(其实代码是次要的,数学原理在这里才是关键所在!)这里的代码据说是赖在 mesa OpenGL 中的!
PS:这里为了更好理解,我修改了一下里面的代码,但没有兼顾效率的!
#include<GL/gl.h>
/*
* Transform a point (column vector) by a 4x4 matrix. I.e. out = m * in
* Input: m - the 4x4 matrix
* in - the 4x1 vector
* Output: out - the resulting 4x1 vector.
*/
],
],
])
{
#define M(row,col) m[col* 4+ row]
] =, ) *] +, ) *] +, ) *] +, ) *];
] =, ) *] +, ) *] +, ) *] +, ) *];
] =, ) *] +, ) *] +, ) *] +, ) *];
] =, ) *] +, ) *] +, ) *] +, ) *];
#undef M
}
GLint gluProject(GLdouble objx,
GLdouble objy,
GLdouble objz,
],
],
],
GLdouble*winx,
GLdouble*winy,
GLdouble*winz) /* transformation matrix */
{
];
], ];
/* initilise matrix and vector transform */
// 4x4 matrix must be multi to a 4 dimension vector( it a 1 x 4 matrix)
// so we need to put the original vertex to a 4D vector
] = objx;
] = objy;
] = objz;
] = 1.0;
// 由于原来的向量位于标准基向量 (1, 0, 0), (0, 1, 0), (0, 0, 1) 中,所以需要先转换到当前的模型矩阵中
transform_point(objModel, model, objCoor);
// 然后将模型矩阵中的顶点转换到投影矩阵所在坐标系的矩阵中
transform_point(objProj, proj, objModel);
// scale matrix
/* GLdouble scaleMat[4][4] =
{ {0.5, 0, 0, objPr0j[3]}, {0, 0.5, 0,
objProj[3]}, {0, 0, 0.5, objProj[3]}, {1, 1, 1,
1} }; GLdouble objProjTemp[4];
memcpy(objProjTemp, objProj, sizeof(objProjTemp);
transfrom_point(objProj, scaleMat, objProjTemp); */
/* or the result of normalized between -1 and 1 */
]== 0.0)
return GL_FALSE;
] /=];
] /=];
] /=]; /* in screen coordinates */
// 由于投影矩阵投影在 [-1, 1] 之间,所以需要将转换后的投影坐标放置到 [0, 1] 之间
// 最后再在一个 offset 矩形中转换为屏幕坐标就可以了( viewport[4] 可以简单的认为一个 offset 矩形)
) /)
] =]);
] =]);
] =]);
#undef SCALE_FROM_0_TO_1
*] +] *];
*] +] *]; /* between 0 and 1 */
*];
return GL_TRUE;
}
基本的思路就是:
1、将输入的顶点,通过模型视图矩阵,变换到模型视图矩阵的坐标系中;
2、将模型视图矩阵中的顶点,再变换到投影矩阵中;
3、将顶点缩放到 [0, 1] 的映射区间中;
4、通过视口的位置和大小, 计算出当前 3D 顶点中的屏幕坐标( 2D 坐标)
gluUnproject
其实 gluUnproject 和 gluProject 是非常类似的, 代码我暂时没有去找,但我认为应该是这样的(其实就是 gluPorject 反过来的过程,只是有一些数学运算要注意一下) :
1、首先,需要将输入的顶点,通过视口变换到 [0, 1] 之间;
2、然后将顶点缩放到 [-1, 1] 之间,就是上面代码中的 scaleMat矩阵的逆矩阵
3、然后乘上投影矩阵的逆矩阵;
4、最后就是乘上模型视图矩阵的逆矩阵; gluProject,这里我暂时还没有验证,待我有空的时候再检查一下是否确实如此!呵呵
逆变换和模拟变换:http://book.51cto.com/art/201002/185504.htm
引用:
gluProject/gluUnProject don't modify these matrices. In the case of gluProject it applies the transformations (the modelview, projection, and viewport) the same way the standard pipeline does.
In the case of gluUnProject(4) they use the inverses of those matrices.
if v is the vertex, M is the modelview matrix, P is the projection matrix, and V is the viewport matrix:
v given in object space
gluProject returns V*P*M*v
v given in screen space
gluUnProject returns Mi*Pi*Vi*v
(where i represents the matrix inverse)
[转]gluProject 和 gluUnproject 的详解的更多相关文章
- Linq之旅:Linq入门详解(Linq to Objects)
示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...
- 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)
一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...
- EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解
前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...
- Java 字符串格式化详解
Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...
- Android Notification 详解(一)——基本操作
Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...
- Android Notification 详解——基本操作
Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...
- Git初探--笔记整理和Git命令详解
几个重要的概念 首先先明确几个概念: WorkPlace : 工作区 Index: 暂存区 Repository: 本地仓库/版本库 Remote: 远程仓库 当在Remote(如Github)上面c ...
- Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)
Android XML shape 标签使用详解 一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...
- Node.js npm 详解
一.npm简介 安装npm请阅读我之前的文章Hello Node中npm安装那一部分,不过只介绍了linux平台,如果是其它平台,有前辈写了更加详细的介绍. npm的全称:Node Package M ...
随机推荐
- InstallShield卸载不彻底,残留大量dll文件
今天发现安装包Client装c盘能正常删除,但是放d盘不能删除dll文件. 1.d盘安装程序包 2.检查脚本文件,卸载时通过messagebox打印INSTALLDIR和TARGERDIR,发现均指向 ...
- C语言 · 递归倒置字符数组
算法提高 递归倒置字符数组 时间限制:1.0s 内存限制:512.0MB 问题描述 完成一个递归程序,倒置字符数组.并打印实现过程 递归逻辑为: 当字符长度等于1时,直接返回 否则, ...
- C语言 · 字符串的展开
算法训练 字符串的展开 时间限制:1.0s 内存限制:256.0MB 在初赛普及组的“阅读程序写结果”的问题中,我们曾给出一个字符串展开的例子:如果在输入的字符串中,含有类似于“d ...
- (DNS)dnsmasq部署DNS
转自:https://www.hi-linux.com/posts/30947.html Dnsmasq提供DNS缓存和DHCP服务.Tftp服务功能.作为域名解析服务器(DNS),Dnsmasq可以 ...
- udev简述
udev 是 Linux 内核的设备管理器.总的来说,它取代了devfs和hotplug,负责管理/dev中的设备节点.同时,udev 也处理所有用户空间发生的硬件添加.删除事件,以及某些特定设备所需 ...
- jmap查看内存使用情况与生成heapdump
jmap查看内存使用情况与生成heapdump 如果想分析自己的JAVA Application时,可以使用jmap程序来生成heapdump文例: jmap -heap 1234 (1234为进程 ...
- [数据结构]最小生成树算法Prim和Kruskal算法
最小生成树 在含有n个顶点的连通图中选择n-1条边,构成一棵极小连通子图,并使该连通子图中n-1条边上权值之和达到最小,则称其为连通网的最小生成树. 例如,对于如上图G4所示的连通网可以有多棵权值总 ...
- 有赞MySQL自动化运维之路—ZanDB
有赞MySQL自动化运维之路—ZanDB 一.前言 在互联网时代,业务规模常常出现爆发式的增长.快速的实例交付,数据库优化以及备份管理等任务都对DBA产生了更高的要求,单纯的凭借记忆力去管理那几十 ...
- SpringCloud 天气预报系统 Quartz集成
https://blog.csdn.net/csdn_wangchen/article/details/79402097 继上一次的redis集成后,有了很大的改观,但是缺少数据的同步.------& ...
- SSD 固态硬盘,Trim指令 ,查看状态、开启、关闭
一说到SSD 固态硬盘,经常会看到Trim指令这个名词,那什么是Trim? Trim是什么? 为了解决硬盘降速的问题,微软联合各大SSD厂商开发了一个新技术——Trim.Trim指令也叫disab ...