视图矩阵的推导

        把物体从世界坐标系转化到视点坐标系的矩阵称为视图矩阵。

     下面我们先看下OpenGL中视图矩阵的推导过程:

     假设视点或camera的局部坐标系为UVN,UVN分别指向右方、上方和后方从而构成右手坐标系,视点则处于局部坐标系的原点位置。

     就如OpenGL中的函数gluLookAt(eyex, eyey, eyez, lookatx, lookaty, lookatz, upx, upy, upz)一样,给定视点、观察点、以及up向量之后,我们就可以求得视图矩阵。

1、首先我们来求得N = eye – lookat,并把N归一化。

2、up和N差积得到U, U= up X N,归一化U。

3、然后N和U差积得到V

假定设定摄像机参数如下:gluLookAt(0.0, 3.0, 4.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

则N=Normalize((0.0,3.0,4.0)-(0.0,0.0,0.0))=Normalize((0.0,3.0,4.0))= (0.0,0.6,0.8)

    U=up X N= (1.0*0.8-0.6*0.0,0.0*0.0-0.0*0.8, 0.0*0.6-0.0*1.0)=(0.8,0.0,0.0), 归一化后为U=(1.0,0.0,0.0)

    V=N X U=(0.0,0.8,-0.6),归一化后为(0.0,0.8,-0.6)

 

 

      假设视点坐标系初始和世界坐标系重合,它先进行一个旋转变化,然后再进行一个平移,得到现在视点位置和方位。则此时进行的矩阵变化为,其中T是平移变化,R是旋转变化,因为OpenGL顶点坐标,使用列向量,所以我们使用逆变换。

T的逆矩阵为:

对gluLookAt(0.0, 3.0, 4.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);  (Tx,Ty,Tz)=(0.0,3.0,4.0)

     当相机变换进行完Inverse Translation这一步之后,相机的原点和世界原点就重合了,也就是处理完了关于平移的变换。

     我们要把一个世界坐标系点K(Kx, Ky, Kz),表示成(U,V,P)坐标系的点(假设此时,已经经过平移操作,摄像机在世界坐标系的原点),则其公式为:

因为(Lx, Ly, Lz)=(Kx,Ky,Kz)*(U,V,P),【因为世界坐标系的三个基乘以(U,V,P),就会把世界坐标系转变到uvp坐标系,所以世界坐标的顶点坐标,乘以这个矩阵,也会转化到uvp坐标系中的顶点坐标】则有

Lx = Kx * Ux + Ky * Uy + Kz * Uz;

Ly = Kx * Vx + Ky * Vy + Kz * Vz;

Lz = Kx * Px + Ky * Py + Kz * Pz

则转化矩阵为:

则完整的公式为:     

 

则gluLookAt(0.0, 3.0, 4.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);最终视图矩阵是

你可以用下面的代码来验证它:

#include <stdio.h>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <stdlib.h> 
#include <cmath>

void init(void)
{
    glClearColor(0.0, 0.0, 0.0, 0.0); //背景黑色 
}

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0, 1.0, 1.0); //画笔白色 

    glLoadIdentity();  //加载单位矩阵 

    gluLookAt(0.0, 3.0, 4.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    glutWireCube(1.0f);
    glutSwapBuffers();
}

 

void reshape(int w, int h)
{
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60.0, (GLfloat)w / (GLfloat)h, 1.0, 20.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0.0, 3.0, 4.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    GLdouble mv[16] = { 0 }, pv[16] = { 0 };
    glGetDoublev( GL_MODELVIEW_MATRIX, mv );
    printf("view1:%5.3f, %5.3f,%5.3f, %5.3f,%5.3f, %5.3f,%5.3f, %5.3f,%5.3f, %5.3f,%5.3f, %5.3f,%5.3f, %5.3f,%5.3f, %5.3f\n", mv[0], mv[1], mv[2], mv[3], mv[4], mv[5], mv[6], mv[7], mv[8], mv[9], mv[10], mv[11], mv[12], mv[13], mv[14], mv[15]);
    glGetDoublev(GL_PROJECTION_MATRIX, pv);

}

 

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowSize(500, 500);
    glutInitWindowPosition(100, 100);
    glutCreateWindow(argv[0]);
    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMainLoop();
    return 0;
}

以上是OpenGL的视图矩阵,对于D3D,由于使用行向量,左乘,以及左手坐标系,所以视图稍有不同,在D3D11教程中,曾加做过推导:

http://www.cnblogs.com/mikewolf2002/archive/2012/03/11/2390669.html

时间: 2024-10-09 17:05:48

视图矩阵的推导的相关文章

[3D基础]投影矩阵的推导(1)

转眼我做游戏行业已经八个月了,游戏行业入门门槛低,所以还算学习得比较轻松,总结了当初自己迷惑的几个知识点,本来想写出来给初学者解惑,无赖我是一个懒散的人,一直拖到现在,终于决心白纸黑字的搬到Blog上来,希望大家喜欢. 投影变换:我觉得这个是3D到2D变换中最让初学者头晕的问题,但又是最重要的. 请看上面这张我用爪子抓出来的图.这个坐标系是DX的左手坐标系,Y向上,X向右,Z向内,几何坐标已经经过了相机坐标系的变换,相机位置为(0,0,0),假设远裁减面距离为f,近裁减面距离为n,近裁减面左边为

镜面反射矩阵推导

最近公司游戏正在准备上线,所以FlasCC也就没有研究了,偶尔有闲功夫,也是玩玩3DMAX和UNITY3D. 感觉不会3DMAX,是一种局限. 回到主题,记录一下镜面反射矩阵的推导. 在用Irrlicht和RTT做镜面效果的时候,用到了反射矩阵. 就是需要把摄相机镜像,渲染一个RT,贴到镜面模型上.这个其实还纠结了许久,因为之前做水面渲染的时候,水面是平的,很好计算摄相机在水面以下的位置. 但是换成镜面,就不一样了,因为镜面可能是任意面. 于是就需要一个通用的反射矩阵. 反射矩阵的计算是基于平面

D3D的投影矩阵推导[转贴]

原帖地址:http://blog.csdn.net/popy007/article/details/4091967       上一篇文章中我们讨论了透视投影变换的原理,分析了OpenGL所使用的透视投影矩阵的生成方法.正如我们所说,不同的图形API因为左右手坐标系.行向量列向量矩阵以及变换范围等等的不同导致了矩阵的差异,可以有几十个不同的透视投影矩阵,但它们的原理大同小异.这次我们准备讨论一下Direct3D(以下简称D3D)的透视投影矩阵,主要出于以下几个目的: (1) 我们在写图形引擎的时

一起学WP7 XNA游戏开发(六. 3d Model的载入)

在XNA中3D Model 一般都是autodesk公司的fbx 格式.载入的方法和2D基本上是一样的,但是在绘制时是有很大不同的. 一.载入: protected override void LoadContent() { tankModel = Content.Load<Model>("tank");//载入fbx model tankBonesTransforms = new Matrix[tankModel.Bones.Count];//创建一个model的bone

[译]基于 Metal 的 ARKit 使用指南(下)

本文讲的是[译]基于 Metal 的 ARKit 使用指南(下), 原文地址:Using ARKit with Metal part 2 原文作者:Marius Horga 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m- 译者:swants 校对者:zhangqippp Danny1451 咱们上篇提到过 , ARKit 应用通常包括三个图层 : 渲染层 , 追踪层 和 场景解析层 .上一篇我们通过一个自定义视图已经非常详细地分析了渲染层在 Metal 中是

逻辑回归那些事—使用牛顿法解决实际问题

更多深度文章,请关注云计算频道:https://yq.aliyun.com/cloud 前言 在本篇博客中,我们要介绍的是牛顿法的原理,并且将之应用到实际的逻辑回归问题中.逻辑回归的主要知识点包括伯努利分布的对数似然和用来平滑的sigmoid函数. 我们还要介绍Hession,这是一个二阶偏导的方阵.看完了本片博客,您就知道如何使用Hession结合梯度来实现牛顿法. 和之前的博客一样,我们这篇也将从牛顿法的整体概述.数学推导以及编程实现几个方面展开.最终将理论和实践的结合,灵活运用牛顿法解决逻

[Qt教程] 第48篇 进阶(八) 3D绘图简介

[Qt教程] 第48篇 进阶(八) 3D绘图简介 楼主  发表于 2013-10-7 09:44:37 | 查看: 184| 回复: 0 3D绘图简介 版权声明 该文章原创于作者yafeilinux,转载请注明出处! 导语 OpenGL是一个跨平台的用来渲染3D图形的标准API.在Qt中提供了QtOpenGL模块,从而很轻松地实现了在Qt应用程序中使用OpenGL,这主要是在QGLWidget类中完成的.因为3D绘图涉及到了专业方面的内容,我们下面只是讲解最简单的使用,向大家演示在Qt中如何显示

最简单的视音频播放示例5:OpenGL播放RGB/YUV

本文记录OpenGL播放视频的技术.OpenGL是一个和Direct3D同一层面的技术.相比于Direct3D,OpenGL具有跨平台的优势.尽管在游戏领域,DirectX的影响力已渐渐超越OpenGL并被大多数PC游戏开发商所采用,但在专业高端绘图领域,OpenGL因为色彩准确,仍然是不能被取代的主角. OpenGL简介 从网上搜集了一些有关OpenGL简介方面的知识,在这里列出来.开放图形库(英语:Open Graphics Library,缩写为OpenGL)是个定义了一个跨编程语言.跨平

webgl-Webgl画6个颜色不同的面的正方体

问题描述 Webgl画6个颜色不同的面的正方体 学WebGL的时候照着书上打了一段代码,结果发现运行到网页上只有背景颜色,没有正方体,看控制台也没有错误信息输出,实在是不知道哪里错了... js的代码 var VSHADER_SOURCE= 'attribute vec4 a_Position;n'+ 'attribute vec4 a_Color;n'+ 'uniform mat4 u_MvpMatrix;n'+ 'varying vec4 v_Color;n'+ 'void main(){n