详解MVP矩阵之齐次坐标和ModelMatrix
来源:互联网 发布:儿童插画 知乎 编辑:程序博客网 时间:2024/06/05 11:39
齐次坐标(Homogeneous Coordinates)
其次坐标这个概念在第一次看real-time rendering 这本书的时候就有提起到,但当时看的一头雾水,只知道其次坐标在某些计算中比较方便,而事实上齐次坐标有着非常重要的意义和作用,主要是在处理三维透视方面,常用的几个地方,比如texture mapping 透视矫正,Projection Matrix的计算等等。
在笛卡尔坐标系中,两条平行线是永不相交的,而在现实中,两条平行线是可能相交于一点的,比如说下面的铁轨。
图一 . 铁路越来越窄,最后汇集到一点
在这种透视空间中,笛卡尔坐标就无法描述了。
解决方案就是齐次坐标,一句话解释,就是用N+1个数来表示N维空间中的点。
比如一个二维坐标(X,Y),它的齐次坐标就是(x, y, w), 关系如下
所以在知道齐次坐标的情况下,可以很方便地得到其笛卡尔坐标。之所以称之为其次坐标,是因为奇次坐标具有缩放不变性,比如(1,2,3),(2,4,6), (1a,2a,3a) 所表达的笛卡尔坐标是一样的!
有了其次坐标我们就可以证明两条平行线相交了。
有两条直线
Ax + By + C = 0
Ax + By + D = 0
很明显他们在平面内是平行线,永不相交(如果C==D的话,两条直线就重合了)
化为其次坐标,
A(x/w) + B(y/w) + C = 0;
A(x/w) + B(y/w) + D = 0;
同乘w,得到
Ax + By + Cw = 0
Ax + By + Dw = 0
则有解 (x,y,0),所以两条平行线相交在(x,y,0),也就是相交在无穷远的点。
ModelMatrix
在Unity中,每一个GameObject上面都会有一个Transform,用来记录这个Object的position,rotation和scale.
图二 . Unity中的Transform Compoent
这三项都可以用矩阵来表示,位移矩阵是
旋转矩阵由Quatenion转过来
R = ( 1.0f - 2.0f*y*y - 2.0f*z*z, 2.0f*x*y - 2.0f*z*w, 2.0f*x*z + 2.0f*y*w, 0.0f, 2.0f*x*y + 2.0f*z*w, 1.0f - 2.0f*x*x - 2.0f*z*z, 2.0f*y*z - 2.0f*x*w, 0.0f, 2.0f*x*z - 2.0f*y*w, 2.0f*y*z + 2.0f*x*w, 1.0f - 2.0f*x*x - 2.0f*y*y, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f )
缩放矩阵
具体的矩阵推导可以参考我之前写的Real-Time Rendering (2) - 变换和矩阵(Transforms and Matrics)。
所谓的ModelMatrix,就是将模型坐标变换到WorldMatrix的Matrix,
WorldMatrix = Mt * Mr * Ms
Vw = WorldMatrix * Vm
注意这里的Matrix都是列主序, Vm是Model坐标系下的坐标,Vw是世界坐标系下的坐标,矩阵是右乘Vm, Vm用的齐次坐标,w = 1.
顺序一定是T*R*S。
Transform Class
这里写一个简单的类来处理GameObejct的位置,旋转和缩放.
Transform.h
#pragma once#include "Quaternion.h"#include "RiCore/RiDevice.h"class Transform{public:Transform();Transform(const Vector3& position, const Quaternion& rotation, const Vector3& scale);~Transform();Matrix4x4 GetLocalToWorldMatrix();bool isDirty;Vector3 position;Quaternion rotation;Vector3 scale;void Translate(const Vector3 &delta);void Rotate(float xRot, float yRot, float zRot);void Scale(const Vector3 &scale);private:Matrix4x4 localToWorldMatrix;Matrix4x4 worldToLocalMatrix;};
Transform.cpp
#include "stableheader.h" #include "Transform.h"#include "Log/Log.h"Transform::Transform(){}Transform::Transform(const Vector3& _position, const Quaternion& _rotation, const Vector3& _scale){position = _position;rotation = _rotation;scale = _scale;isDirty = true;}Transform::~Transform(){}Matrix4x4 Transform::GetLocalToWorldMatrix(){if (isDirty){Matrix4x4 transMatrix(1, 0, 0, 0,0, 1, 0, 0,0, 0, 1, 0,position.x, position.y, position.z, 1);Matrix4x4 scaleMatrix(scale.x, 0, 0, 0,0, scale.y, 0, 0,0, 0, scale.z, 0,0, 0, 0, 1);localToWorldMatrix = transMatrix * rotation.GetRotMatrix() * scaleMatrix;}return localToWorldMatrix;}void Transform::Translate(const Vector3 &delta){position.x += delta.x;position.y += delta.y;position.z += delta.z;isDirty = true;}void Transform::Rotate(float xRot, float yRot, float zRot){rotation = rotation * Quaternion::Euler(xRot, yRot, zRot);isDirty = true;}Matrix4x4 Transform :: Scale(const Vector3& _scale){scale = _scale;isDirty = true;}
用了一个标志位来记录position,rotation,scale是否发生改变,如果发生改变就将isDirty至为true,下次获取WorldMatrix的时候就重新计算。
测试
//Unitytransform.position = new Vector3(1, 2, 3);transform.rotation = Quaternion.Euler(30, 45, 60);transform.localScale = new Vector3(3, 2, 1);Debug.Log(transform.localToWorldMatrix);
图三 . Unity中的运行结果
//C++renderObj = new RenderObject();renderObj->transform->Translate(Vector3(1, 2, 3));renderObj->transform->Rotate(30, 45, 60);renderObj->transform->Scale(Vector3(3, 2, 1));qDebug() << renderObj->transform->GetLocalToWorldMatrix();
参考
Tutorial 3 : Matrices - http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/
OpenGL Transformation - http://www.songho.ca/opengl/gl_transform.html#modelview
Homogeneous Coordinates - http://www.songho.ca/math/homogeneous/homogeneous.html
The Truth Behind Homogeneous Coordinates - http://deltaorange.com/2012/03/08/the-truth-behind-homogenous-coordinates/
Real Time Rendering 3rd
链接
详解MVP矩阵之齐次坐标和ModelMatrix
详解MVP矩阵之齐次坐标和ViewMatrix
详解MVP矩阵之齐次坐标和ProjectionMatrix
- 详解MVP矩阵之齐次坐标和ModelMatrix
- MVP矩阵之齐次坐标和ModelMatrix
- 详解MVP矩阵之ViewMatrix
- 详解MVP矩阵之ProjectionMatrix
- 计算机图形学(四)几何变换_2_矩阵表示_1_矩阵表示和齐次坐标
- 齐次坐标详解与普通坐标之间的转换
- 齐次坐标概念&&透视投影矩阵推导
- opengl基础之--齐次坐标
- 齐次坐标
- 齐次坐标
- 齐次坐标2
- 齐次坐标
- 齐次坐标
- 关于齐次坐标
- 齐次坐标
- 齐次坐标
- 齐次坐标
- 齐次坐标
- UVALIVE 3516(DP)
- 《雾兮霾兮》
- 热补丁介绍及Andfix的使用
- 多线程:UIView 动画案例
- Pycharm使用笔记
- 详解MVP矩阵之齐次坐标和ModelMatrix
- 多线程:block 演练
- 游标使用效率对比
- You need to use a Theme.AppCompat theme (or descendant) with this activity解决方法
- CentOS-6.5下编译安装LNMP环境【nginx1.8.1、mysql5.5.43、php 5.6】
- key word
- 弦月下的SQL<2> 数据库管理
- 代码大全_第3部分: 变量
- 删除docker0网卡