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不为0x /= 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()函数究竟对矩阵做了什么相关推荐

  1. OpenGL中投影函数glOrtho()、glFrustum()以及gluPerspective()以及函数的用法

    OpenGL中,如果想对模型进行操作,就要对这个模型的状态(当前的矩阵)乘上这个操作对应的一个矩阵. 如果乘以变换矩阵(平移, 缩放, 旋转), 那相乘之后, 模型的位置被变换; 如果乘以投影矩阵(将 ...

  2. 【OpenGL】关于OpenGL中Bind函数的理解

    在OpenGL中,总是会遇到类似下面的绑定语句: glBindTexture(GL_TEXTURE_2D, renderTex); glBindFramebuffer(GL_FRAMEBUFFER, ...

  3. OpenGL中平移函数glTranslatef()、旋转函数glRotatef()的理解

    https://blog.csdn.net/tan_handsome/article/details/50614146 void glTranslatef(GLfloat x,GLfloat y,GL ...

  4. OpenGL中平移函数glTranslatef()、旋转函数glRotatef()的理解(非常好的文章)

    void glTranslatef(GLfloat x,GLfloat y,GLfloat z); 函数功能:沿X轴正方向平移x个单位(x是有符号数)   沿Y轴正方向平移y个单位(y是有符号数)   ...

  5. 计算机图形学OpenGL中的glLoadIdentity、glTranslatef、glRotatef原理,用法

    单位矩阵 对角线上都是1,其余元素皆为0的矩阵. 在矩阵的乘法中,有一种矩阵起着特殊的作用,如同数的乘法中的1,我们称这种矩阵为单位矩阵. 它是个方阵,除左上角到右下角的对角线(称为主对角线)上的元素 ...

  6. 计算机图形学OpenGL中的glLoadIdentity、glTranslatef、glRotatef原理,用法 .(转)

    单位矩阵 对角线上都是1,其余元素皆为0的矩阵. 在矩阵的乘法中,有一种矩阵起着特殊的作用,如同数的乘法中的1,我们称这种矩阵为单位矩阵. 它是个方阵,除左上角到右下角的对角线(称为主对角线)上的元素 ...

  7. OpenGL中glPushMatrix和glPopMatrix的原理

    glPushMatrix.glPopMatrix操作事实上就相当于栈里的入栈和出栈. 很多人不明确的可能是入的是什么,出的又是什么. 比如你当前的坐标系原点在你电脑屏幕的左上方.如今你调用glPush ...

  8. mysql中week()函数

    mysql中week()函数是用来做周的统计和计算,返回日期的周数 例如统计今年每周有多少个注册用户 SELECT count(id) as count,week(create_time,1) as ...

  9. mysql中week()函数的用法

    mysql中week()函数是用来做周的统计和计算,返回日期的周数 例如统计今年每周有多少个注册用户 SELECT count(id) as count,week(create_time,1) as ...

最新文章

  1. JAVA----------------------华为机试--------------------------删除字符串中出现次数最少的字符...
  2. TKStudio-LPC1220_GPIO_LED工程后记
  3. Android中的多种文件读写操作方法
  4. 2008年3月移动开发Webcast预告
  5. bzoj 1641: [Usaco2007 Nov]Cow Hurdles 奶牛跨栏(floyd)
  6. windows下MongoDB数据库的安装
  7. Domino中运用ajax判断帐号是否存在的简单例子
  8. atan和atan2反正切计算
  9. 并发编程学习之AQS抽象队列同步器
  10. 机器人避障技术解读 与解决方案
  11. Arcview GIS应用与开发技术(12)-3D分析
  12. sqlserver内存释放心得
  13. 蓝桥杯官网 试题 PREV-113 历届真题 估计人数【第十届】【决赛】【研究生组】【C++】【Java】【Python】三种解法
  14. web图书销售管理系统_美萍手机销售WEB版销售管理系统整体解决方案服务商
  15. 深度学习教程(12) | CNN应用:目标检测(吴恩达·完整版)
  16. WPS标题段前间距设置无效解决方案
  17. linux下解压rpm包,linux下 各种解压文件使用方法
  18. Linux操作命令分类详解 - 目录文件(二)
  19. 循环栅栏 CycleBarrier 理解到深入
  20. Java虚拟机学习笔记(一)—Java虚拟机概述

热门文章

  1. Java经典面试题—— int 和 Integer 有什么区别?谈谈 Integer 的值缓存范围
  2. Linux常用的终端操作命令
  3. Clion注册码与注册机
  4. 长篇分享腾讯工作的环境、待遇等
  5. 淘宝客如何通过闲鱼引流?淘宝客、闲鱼营销推广方式有哪些?
  6. MongoDB未授权访问
  7. 医学统计学 第四章(定量资料的统计描述)
  8. 代码实现 —— 多项式的最大公因式(线性代数)
  9. 多源异构作物组学数据融合方法研究——以高粱为例
  10. 医疗大数据 隐私保护_大数据环境中的医疗数据隐私保护