OpenGL中glRotatef()函数究竟对矩阵做了什么
OpenGL中glRotatef()函数究竟对矩阵做了什么
我们知道OpenGL中维持着两套矩阵,一个是模型视图矩阵(model view matrix),另一个是投影矩阵(projection matrix)。而Direct3D维持着三个矩阵,其实它们的本质是一样的,因为Model(World)矩阵×View矩阵 = ModelView矩阵,也就是OpenGL的模型视图矩阵。通过对OpenGL这两套矩阵的变换,我们可以得到各种投影效果。这回我就来研究OpenGL中一个常见的函数glRotatef(d)。
看参数,glRotatef( angle, x, y, z )函数的作用是将当前坐标系以a( x, y, z )向量为旋转轴旋转angle角度。这种方法可以以简单明白的方式将世界坐标系进行旋转。但是在内部,OpenGL究竟是用什么公式对其进行旋转呢?
原创文章,反对未声明的引用。原博客地址:http://blog.csdn.net/gamesdev/article/details/9929211
为了弄清楚真相,我们开始研究矩阵的相关知识。首先,我们考虑单位矩阵I在绕着坐标轴旋转后所得的旋转矩阵。这里我直接列出了三种情况:
知道了绕着三轴后的旋转矩阵,那么下面就是绕任意向量所得的矩阵了。设M为单位矩阵经向量a旋转后的矩阵,且a = (xa, ya, za),旋转角度为α,则M=
我其实也不明白该如何证明的,不过我们可以编写一个小程序来验证一下:
#include <assert.h>
#include <stdio.h>
#include <math.h>
#include "GLWidget.h" void PrintMatrix( float matrix[16] )
{
assert( matrix != 0 );
printf( "%8.2f%8.2f%8.2f%8.2f\n"
"%8.2f%8.2f%8.2f%8.2f\n"
"%8.2f%8.2f%8.2f%8.2f\n"
"%8.2f%8.2f%8.2f%8.2f\n",
matrix[0], matrix[1], matrix[2], matrix[3],
matrix[4], matrix[5], matrix[6], matrix[7],
matrix[8], matrix[9], matrix[10], matrix[11],
matrix[12], matrix[13], matrix[14], matrix[15] );
} void MyRotatef( float matrix[16],
float angleInDegree,
float x,
float y,
float z )
{
assert( matrix != 0 ); // 向量的单位化
float length = sqrt( x * x + y * y + z * z );
assert( !qFuzzyCompare( length, 0.0f ) );// 希望length不为0 x /= length;
y /= length;
z /= length; float alpha = angleInDegree / 180 * 3.1415926;// 已转换弧度制
float s = sin( alpha );
float c = cos( alpha );
float t = 1.0f - c; #define MATRIX( row, col ) matrix[row * 4 + col]
MATRIX( 0, 0 ) = t * x * x + c;
MATRIX( 0, 1 ) = t * x * y + s * z;
MATRIX( 0, 2 ) = t * x * z - s * y;
MATRIX( 0, 3 ) = 0.0f;
MATRIX( 1, 0 ) = t * x * y - s * z;
MATRIX( 1, 1 ) = t * y * y + c;
MATRIX( 1, 2 ) = t * y * z + s * x;
MATRIX( 1, 3 ) = 0.0f;
MATRIX( 2, 0 ) = t * x * z + s * y;
MATRIX( 2, 1 ) = t * y * z - s * x;
MATRIX( 2, 2 ) = t * z * z + c;
MATRIX( 2, 3 ) = 0.0f;
MATRIX( 3, 0 ) = 0.0f;
MATRIX( 3, 1 ) = 0.0f;
MATRIX( 3, 2 ) = 0.0f;
MATRIX( 3, 3 ) = 1.0f;
#undef MATRIX
} GLWidget::GLWidget( QWidget* pParent ):
QGLWidget( pParent )
{
setWindowTitle( "Test OpenGL Matrix" );
} void GLWidget::initializeGL( void )
{
float angle = 30.0f;
float x = 12.0f;
float y = 8.0f;
float z = 3.0f; float matrix1[16], matrix2[16];
glMatrixMode( GL_MODELVIEW );
glLoadIdentity( );
glGetFloatv( GL_MODELVIEW_MATRIX, matrix1 );
glGetFloatv( GL_MODELVIEW_MATRIX, matrix2 ); printf( "The initial identity matrix is:\n" );
PrintMatrix( matrix2 );
printf( "Now perform OpenGL glRotate function.\n" );
glRotatef( angle, x, y, z );
glGetFloatv( GL_MODELVIEW_MATRIX, matrix1 );
PrintMatrix( matrix1 ); printf( "Now perform MyRotate function.\n" );
MyRotatef( matrix2, angle, x, y, z );
PrintMatrix( matrix2 );
} void GLWidget::paintGL( void )
{ }
程序的运行结果如下:
这说明上面的这条公式是正确的。如此一来我们就知道了glRotatef()的原理啦。其实D3DXMatrixRotationAxis()函数也是这样操作的,只不过D3D是左手坐标系,它的矩阵构建方法又会有所不同。
OpenGL中glRotatef()函数究竟对矩阵做了什么的更多相关文章
- OpenGL中两种计算投影矩阵的函数
OpenGL无意间同时看到两种创建投影矩阵的写法,可以说它们完成的是同样的功能,但写法完全不同,可以观摩一下什么叫做异曲同工之妙... 第一种: gltMakeShadowMatrix函数是重点 // ...
- js中在一个函数中引用另一个函数中的函数,可以这么做
在另一个函数中,将需要使用的函数绑定在window下 // UEditor $(function () { window.ue = UE.getEditor('editor', { // ue即可成为 ...
- 计算机图形学OpenGL中的glLoadIdentity、glTranslatef、glRotatef原理,用法 .(转)
单位矩阵 对角线上都是1,其余元素皆为0的矩阵. 在矩阵的乘法中,有一种矩阵起着特殊的作用,如同数的乘法中的1,我们称这种矩阵为单位矩阵. 它是个方阵,除左上角到右下角的对角线(称为主对角线)上的元素 ...
- OpenGL中平移、旋转、缩放矩阵堆栈操作
在OpenGL中,图元的几何变换均为线性变换,通过矩阵变换实现.OpenGL中的坐标用齐次坐标表示,即(x,y,z)表示成(x',y',z',h),其中x=x'/h; y=y'/h; z=z'/h. ...
- (转)思考:矩阵及变换,以及矩阵在DirectX和OpenGL中的运用问题:左乘/右乘,行优先/列优先,...
转自:http://www.cnblogs.com/soroman/archive/2008/03/21/1115571.html 思考:矩阵及变换,以及矩阵在DirectX和OpenGL中的运用1. ...
- OpenGL中glPushMatrix和glPopMatrix的原理
glPushMatrix.glPopMatrix操作事实上就相当于栈里的入栈和出栈. 很多人不明确的可能是入的是什么,出的又是什么. 比如你当前的坐标系原点在你电脑屏幕的左上方.如今你调用glPush ...
- OpenGL中坐标系的理解(一)
在OpenGL中,存在着至少存在着三种矩阵,对应着函数glMatrixMode()的三个参数:GL_MODELVIEW,GL_PROJECTION,GL_TEXTURE. 以下主要描述GL_MODEL ...
- OpenGL中常用的函数
OPengl的官方文档如下:https://www.opengl.org/sdk/docs/man4/ void glGetIntegerv( GLenum pname, GLint * ...
- 关于opengl中的矩阵平移,矩阵旋转,推导过程理解 OpenGL计算机图形学的一些必要矩阵运算知识
原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/12166896.html 为什么引入齐次坐标的变换矩阵可以表示平移呢? - Yu Mao的回答 ...
随机推荐
- Java-Poi 读取excel 数据
一直想着使用java操作excel,但有时各种原因一直没有实现.由于工作无意间做了个其他demo,为了进一步发散就涉及到了使用excel,为此开始正式接触POI,虽然限制不是很了解POI,但是通过查阅 ...
- FileProvider是个什么东西?
FileProvider是个什么东西? 在<读取并监控文件的变化>中,我们通过三个简单的实例演示从编程的角度对文件系统做了初步的体验,接下来我们继续从设计的角度来继续认识它.这个抽象的文件 ...
- Linux07--Shell程序设计03 通配符与正则表达式
通配符 通配符可用于代替字符. 通常地,星号“*”匹配0个或以上的字符,问号“?”匹配1个字符. 使用情况: 1.文件和目录 在CP/M.DOS.Microsoft Windows和类Unix操作系统 ...
- Oracle EBS-SQL (WIP-12):总装车间任务查询.sql
select WT.WIP_ENTITY_NAME 任务名 ...
- js cookie读取
/**存放Cookies: 两个参数,一个是cookie的名子,一个是值*/ function SetCookie(name,value){ var Days = 30; //此 cookie 将被保 ...
- JAVA之数组查询binarySearch()方法详解
binarySearch()方法提供了多种重载形式,用于满足各种类型数组的查找需要,binarySearch()有两种参数类型 注:此法为二分搜索法,故查询前需要用sort()方法将数组排序,如果数组 ...
- Linux学习笔记4-三种不同类型的软件的安装(绿色软件、rpm软件、源代码软件)
在Linux下软件分三种: 1.绿色软件:即不用安装直接就能用的软件 2.rpm安装包:以rpm结尾的可执行文件 3.源码文件:没有进行过编译和打包的文件,需要编译后再进行安装 一.绿色软件的安装 ...
- 如何同时激活两个不同版本的MyEclipse 【MyEclipse2013和MyEclipse2014同时激活】
激活一个MyEclipse的步骤,大家都会,在这里就不多说了,不会的可以看:http://jingyan.baidu.com/article/3ea51489cc14d452e71bba7a.html ...
- Hibernate 多表关联映射- 一对多关系映射(one-to-many)
Hibernage.cfg.xml: <hibernate-configuration> <session-factory name="sessionFactory&quo ...
- html表单提交的几种方法
原文地址:http://www.ijser.cn/?p=34 最普通最经常使用最一般的方法就是用submit type..看代码: <form name=”form” method=”post” ...