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的回答 ...
随机推荐
- Redis深入学习(1)前言&Redis简介
前言 最近工作上使用到Redis,当然以前也使用过redis,win,linux上都使用过,不系统,不深入,仅是头痛医头,脚痛医脚,这里整理一下自己的笔记,一来方便自己记忆,二来对同行提供借鉴,不足错 ...
- QJ系列笔记
1.求int型数据在内存中存储时1的个数输入一个int型数据,计算出该int型数据在内存中存储时1的个数. #include<stdio.h> void main() { ; int yu ...
- Dialog 顶部黑线问题
Dialog 顶部黑线问题 样式如下: [java] view plaincopyprint? <style name="Transparent_Dialog"> &l ...
- POJ 3104 Drying(二分答案)
[题目链接] http://poj.org/problem?id=3104 [题目大意] 给出n件需要干燥的衣服,烘干机能够每秒干燥k水分, 不在烘干的衣服本身每秒能干燥1水分 求出最少需要干燥的时间 ...
- 【转】浅析terminal创建时ptmx和pts关系
我们打开一个terminal,那么将会在devpts文件系统/dev/pts下创建一个对应的pts字符文件,该pts字符文件节点直接由/dev/ptmx节点的驱动函数ptmx_open()调用de ...
- 理解Unity加载和内存管理
转自:http://game.ceeger.com/forum/read.php?tid=4394#info Unity里有两种动态加载机制:一是Resources.Load,一是通过AssetBun ...
- 将Controller中的数据传递到View中显示
如何将Controller 中的数据传送到View 步骤: (1)要有数据,如果要用到对象可以在Model 中定义对应的类 (2)要有装数据的容器: System.Text.StringBuilder ...
- 04737_C++程序设计_第1章_认识C++的对象
例1.1 演示使用结构对象的示例程序. //功能:将结构对象的两个域值相加,乘以2再加50 #include <iostream>//包含头文件 using namespace std;/ ...
- 嵌入式OS入门笔记-以RTX为案例:六.RTX的任务调度
嵌入式OS入门笔记-以RTX为案例:六.RTX的任务调度 上一篇笔记介绍了一些绕开排程器(或调度程序,scheduler)来进行时间管理的一些小方法.这一篇详细介绍RTX的任务调度原理. RTX主要有 ...
- UTL_FILE 的用法
UTL_FILE 的用法 UTL_FILE 是用来进行文件IO处理的专用包,使用这外包的注意事项如下: 1. 生成的文件好象只能放置在DATABASE所在的服务器路径中. 2. 生成的文件如何DO ...