从Model Space到Canonical view volume转换矩阵的计算
来源:互联网 发布:淘宝上最正宗的冷吃兔 编辑:程序博客网 时间:2024/06/05 17:50
从Model Space到Canonical view volume转换矩阵的计算
(2011-10-12 13:18:39)转载▼
标签:
canonical
view
volume
model
space
3d
opengl
矩阵
分类: 技术一、计算旋转矩阵RotateMatrix 3D中绕任意轴n(单位向量)旋转θ 的公式推导见书《3D数学基础:图形与游戏开发》第91页(8.2.3 3D中绕任意轴的旋转)一节,贴出公式如下公式8.5。旋转矩阵R(n,θ)为:
float ax, float ay, float az,//旋转轴 float m[16])//旋转矩阵 float radians, sine, cosine, ab, bc, ca, tx, ty, tz; float axis[3]; float mag;
axis[0] = ax; axis[1] = ay; axis[2] = az; mag = sqrt(axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2]); if (mag) { axis[0] /= mag; axis[1] /= mag; axis[2] /= mag; }
radians = angle * myPi / 180.0;//弧度转换 sine = sin(radians); cosine = cos(radians); ab = axis[0] * axis[1] * (1 - cosine); bc = axis[1] * axis[2] * (1 - cosine); ca = axis[2] * axis[0] * (1 - cosine); tx = axis[0] * axis[0]; ty = axis[1] * axis[1]; tz = axis[2] * axis[2];
m[0] = tx + cosine * (1 - tx); m[1] = ab + axis[2] * sine; m[2] = ca - axis[1] * sine; m[3] = 0.0f; m[4] = ab - axis[2] * sine; m[5] = ty + cosine * (1 - ty); m[6] = bc + axis[0] * sine; m[7] = 0.0f; m[8] = ca + axis[1] * sine; m[9] = bc - axis[0] * sine; m[10] = tz + cosine * (1 - tz); m[11] = 0; m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1;
位移矩阵比较简单,在列主序矩阵中,即在第四列前三元素为位移量,左上3X3矩阵为单位正矩阵。
适用于OPENGL(右手坐标系)的实现程序: m[0] = 1; m[1] = 0; m[2] = 0; m[3] = x; m[4] = 0; m[5] = 1; m[6] = 0; m[7] = y; m[8] = 0; m[9] = 0; m[10] = 1; m[11] = z; m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1;
模型矩阵的功能就是将模型空间转化为世界坐标系。因为我们创作某个模型时是在模型自身的坐标系内完成的,而要描述模型间的相对位置关系时,需要引入世界坐标系。所以需要进行顶点坐标从模型空间转换为世界坐标空间。转换公式为: ModelMatrix = TranslateMatrix * RotateMatrix (先移位后旋转)
每个人都是从各自的视点出发观察这个世界,无论是主观世界还是客观世界。同样,在计算机中每次只能从唯一的视角出发渲染物体。在游戏中,都会提供视点漫游的功能,屏幕显示的内容随着视点的变化而变化。这是因为GPU 将物体顶点坐标从world space 转换到了eye space。所谓eye space,即以camera(视点或相机)为原点,由视线方向、视角和远近平面,共同组成一个梯形体的三维空间,称之为viewing frustum(视锥), 在GPU管线(pipeline)中,通过ViewMatrix * ModelMatrix将模型坐标空间的坐标转换为世界坐标空间,再转换为眼坐标空间。转换公式为: ModelViewMatrix = ViewMatrix * ModelMatrix 关于眼坐标空间中ViewMatrix的计算见我的博客《关于ViewMatrix计算》一节。
透视投影是GPU流水线的重要组成部分,是将相机空间中的点从视锥体(frustum)变换到规则观察体(Canonical
View
Volume)中,待裁剪完毕后进行透视除法的行为。在算法中它是通过透视矩阵乘法和透视除法两步完成的。投影矩阵公式为:
其中, N:为眼睛或摄像机中心到近裁剪面的距离; F:为眼睛或摄像机中心到远裁剪面的距离; left:为投影平面左边界值; right:为投影平面右边界值; top:为投影平面上边界值; bottom:为投影平面下边界值; M即为最终投影变换矩阵。相机空间中的顶点,如果在视锥体中,则变换后就在CVV中。如果在视锥体外,变换后就在CVV外。而CVV本身的规则性对于多边形的裁剪很有利。OpenGL在构建透视投影矩阵的时候就使用了M的形式。注意到M的最后一行不是(0 0 0 1)而是(0 0 -1 0),因此可以看出透视变换不是一种仿射变换,它是非线性的。另外一点你可能已经想到,对于投影面来说,它的宽和高大多数情况下不同,即宽高比不为1,比 如640/480。而CVV的宽高是相同的,即宽高比永远是1。这就造成了多边形的失真现象,比如一个投影面上的正方形在CVV的面上可能变成了一个长方 形。解决这个问题的方法就是在对多变形进行透视变换、裁剪、透视除法之后,在归一化的设备坐标(Normalized Device Coordinates)上进行的视口(viewport)变换中进行校正,它会把归一化的顶点之间按照和投影面上相同的比例变换到视口中,从而解除透视 投影变换带来的失真现象。进行校正前提就是要使投影平面的宽高比和视口的宽高比相同。 fov即视野,是视锥体在xz平面或者yz平面的开角角度,具体哪个平面都可以。OpenGL和 D3D都使用yz平面。 aspect即投影平面的宽高比。 near是近裁剪平面的距离。 far是远裁剪平面的距离。
在程序中,读者朋友您可能对于投影变换的计算很迥异,因为这和上面的公式完全不同形式。但是,当你深入了解其本质后,你会发现,其实他们是同质的。 aspectRatio = right/top top = N * tan(fov/2) bottom = -top right = top * aspectRatio right = -left
double aspectRatio,//width / height double zNear, double zFar, float m[16]) double sine, cotangent, deltaZ; double radians = fieldOfView / 2.0 * myPi / 180.0; deltaZ = zFar - zNear; sine = sin(radians); // Should be non-zero to avoid division by zero. assert(deltaZ); assert(sine); assert(aspectRatio); cotangent = cos(radians) / sine;
m[0*4+0] = cotangent / aspectRatio; m[0*4+1] = 0.0; m[0*4+2] = 0.0; m[0*4+3] = 0.0; m[1*4+0] = 0.0; m[1*4+1] = cotangent; m[1*4+2] = 0.0; m[1*4+3] = 0.0; m[2*4+0] = 0.0; m[2*4+1] = 0.0; m[2*4+2] = -(zFar + zNear) / deltaZ; m[2*4+3] = -2 * zNear * zFar / deltaZ; m[3*4+0] = 0.0; m[3*4+1] = 0.0; m[3*4+2] = -1; m[3*4+3] = 0;
通过ModelViewProjMatrix矩阵就可以使从模型坐标空间的坐标变换到CVV(规范立方体,Canonical view
volume, CVV)空间坐标了,该立方体的对角顶点分别是(-1,-1,-1)和(1,1,1),CVV 的近平面(梯形体较小的矩形面)的X、Y 坐标对应屏幕像素坐标(左下角是0、0),Z 坐标则是代表画面像素深度。 modelViewProjMatrix = projectionMatrix * modelViewMatrix 至此,完成了从模型坐标空间到CVV的坐标转换。其简图示意为:
(此图来自于The Cg Tutorial)
在自己学习的过程中,将这些难点整理出来,请雅正。同时希望能对正在阅读的您也有所帮助,最重要的还是动手去实现,再结合一些经典教材去理解。个人觉得这样才能有更深刻的理解。
适用于OPENGL(右手坐标系)的实现程序:
void makeRotateMatrix(float angle,//旋转角度 单位:度
{
}
二、计算位移矩阵
典型的位移矩阵为:
适用于OPENGL(右手坐标系)的实现程序:
void makeTranslateMatrix(float x, float y, float z, float m[16])
{
}
三、计算ModelMatrix
四、计算ModelViewMatrix(模型坐标转换为眼坐标空间)
如图 4 所示。近平面,是梯形体较小的矩形面,作为投影平面,远平面是梯形体较大的矩形,在这个梯形体中的所有顶点数据是可见的,而超出这个梯形体之外的场景数据,会被视点去除(Frustum Culling,也称之为视锥裁剪)。(摘自GPU Programming and Cg language Primer)
五、投影矩阵(ProjMatrix)的计算(理解这一部分非常重要)
View
Volume)中,待裁剪完毕后进行透视除法的行为。在算法中它是通过透视矩阵乘法和透视除法两步完成的。投影矩阵公式为:
gluPerspective(fov, aspect, near, far)
(本节部分材料摘自未知姓名的网友word文档,未能找到相关链接,在此表示感谢!)
适用于OPENGL的程序实现:
在上面公式中隐含着这样一些条件:
化简上面的M后,投影矩阵变为:
然后再结合下面程序理解,就应该明了。
void buildPerspectiveMatrix(double fieldOfView,
{
}
五、计算ModelViewProjMatrix
volume, CVV)空间坐标了,该立方体的对角顶点分别是(-1,-1,-1)和(1,1,1),CVV 的近平面(梯形体较小的矩形面)的X、Y 坐标对应屏幕像素坐标(左下角是0、0),Z 坐标则是代表画面像素深度。
。ModelViewProjMatrix计算公式为:
(此图来自于The Cg Tutorial)
程序选自:NVIDIA Corporation\Cg\examples\OpenGL\basic\08_vertex_transform
0 0
- 从Model Space到Canonical view volume转换矩阵的计算
- WEB开发的套路——从MODEL到VIEW
- 从X-Space转换到UCenter Home的方法
- 从MVC到Model-View-Delegate
- 法线从object space到eye space的转换((normal matrix)
- 法线从object space到eye space的转换((normal matrix)
- 法线从object space到eye space的转换((normal matrix)
- 从多元方程组到矩阵计算的乘法法则
- 从单调栈到计算1的矩阵
- 从nova-volume迁移到cinder的一些提示
- 计算一个矩阵从左上角到右下角和最大
- 从object space 到world space
- 有关free-space model的两个形式转换(一个是dB,另外个是除法)
- Qt的Model/View
- Qt 的Model/View
- Qt的model/view
- Gwt从Host Model到 Web Model
- 从矩阵左上角到右下角的最大值
- web前端之轮播实现自动播放。
- Oracle11g单机环境安装配置
- Spring-boot-1.4.0.jar包目录结构
- 图像形状特征(四)--轮廓树及PGH
- Sine之舞
- 从Model Space到Canonical view volume转换矩阵的计算
- 自定义Dialog
- 数字图像处理
- 润乾报表性能管理之集群缓存同步功能
- elasticsearch不能以root运行的问题
- pycmenu使用说明
- Android NestedScrolling机制完全解析 带你玩转嵌套滑动
- CODEVS 1010 过河卒(棋盘型DP)
- Vue.js和MVVM的小细节