当前位置: 首页 > article >正文

Open GL ES ->模型矩阵、视图矩阵、投影矩阵等变换矩阵数学推导以及方法接口说明

Open GL ES 变换矩阵详解

一、坐标空间变换流程

局部空间 ->Model Matrix(模型矩阵)-> 世界空间
世界空间->View Matrix(视图矩阵)->观察空间
观察空间 ->Projection Matrix(投影矩阵)->裁剪空间
裁剪空间 ->ViewPort Transform(视口变换)>屏幕空间

二、变换矩阵及计算

1. 模型矩阵Model Matrix

  • 方法: Matrix.rotateM(), Matrix.translateM(), Matrix.scaleM()
  • 公式:
  • 位移、缩放计算过程
[ Scale_x    0        0      Translation_x ]   [ x ]   [ Scale_x·x + Translation_x ]
[ 0       Scale_y     0      Translation_y ] × [ y ] = [ Scale_y·y + Translation_y ]
[ 0          0     Scale_z   Translation_z ]   [ z ]   [ Scale_z·z + Translation_z ]
[ 0          0        0            1       ]   [ 1 ]   [            1             ]
  • 旋转计算过程
[ cos(θ)  -sin(θ)   0    0 ]   [ x ]   [ x·cos(θ) - y·sin(θ) ]
[ sin(θ)   cos(θ)   0    0 ] × [ y ] = [ x·sin(θ) + y·cos(θ) ]
[   0        0      1    0 ]   [ z ]   [          z          ]
[   0        0      0    1 ]   [ 1 ]   [          1          ]

2. 视图矩阵View Matrix

  • 方法: Matrix.setLookAtM(float[] rm, int rmOffset, float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ)
  • 参数说明:
    eyeX, eyeY, eyeZ: 相机位置坐标
    centerX, centerY, centerZ: 物体位置坐标
    upX, upY, upZ: 相机上方向向量(通常为(0,1,0)
  • 数学函数定义:
  • 向量归一化normalize:
normalize(v) = v / |v|
  • 其中|v|是向量v的长度(模):
|v| =(v.x² + v.y² + v.z²)
  • 向量叉积cross product:
cross(a, b) = [a.y·b.z - a.z·b.y, a.z·b.x - a.x·b.z, a.x·b.y - a.y·b.x]
  • 向量点积dot product:
dot(a, b) = a.x·b.x + a.y·b.y + a.z·b.z
  • 计算过程:
  • 计算前方向向量: Front = normalize(Center - Eye)
Front.x = (centerX - eyeX) / √[(centerX - eyeX)² + (centerY - eyeY)² + (centerZ - eyeZ)²]
Front.y = (centerY - eyeY) / √[(centerX - eyeX)² + (centerY - eyeY)² + (centerZ - eyeZ)²]
Front.z = (centerZ - eyeZ) / √[(centerX - eyeX)² + (centerY - eyeY)² + (centerZ - eyeZ)²]
  • 计算右方向向量: Right = normalize(cross(Front, Up))
Right.x = (Front.y·upZ - Front.z·upY) / √[(Front.y·upZ - Front.z·upY)² + (Front.z·upX - Front.x·upZ)² + (Front.x·upY - Front.y·upX)²]
Right.y = (Front.z·upX - Front.x·upZ) / √[(Front.y·upZ - Front.z·upY)² + (Front.z·upX - Front.x·upZ)² + (Front.x·upY - Front.y·upX)²]
Right.z = (Front.x·upY - Front.y·upX) / √[(Front.y·upZ - Front.z·upY)² + (Front.z·upX - Front.x·upZ)² + (Front.x·upY - Front.y·upX)²]
  • 重新计算上方向向量(确保正交): Up = cross(Right, Front)
Up.x = Right.y·Front.z - Right.z·Front.y
Up.y = Right.z·Front.x - Right.x·Front.z
Up.z = Right.x·Front.y - Right.y·Front.x

(此处Up已经是单位向量,因为RightFront都是单位向量且相互垂直)
公式:

[ Right_x   Right_y   Right_z   -dot(Right,Eye) ]   [ x ]   [ Right_x·x + Right_y·y + Right_z·z - dot(Right,Eye) ]
[ Up_x      Up_y      Up_z      -dot(Up,Eye)    ] × [ y ] = [ Up_x·x + Up_y·y + Up_z·z - dot(Up,Eye)          ]
[ -Front_x  -Front_y  -Front_z   dot(Front,Eye) ]   [ z ]   [ -Front_x·x - Front_y·y - Front_z·z + dot(Front,Eye) ]
[ 0         0         0          1              ]   [ 1 ]   [                       1                          ]

其中:

dot(Right,Eye) = Right.x·eyeX + Right.y·eyeY + Right.z·eyeZ
dot(Up,Eye) = Up.x·eyeX + Up.y·eyeY + Up.z·eyeZ
dot(Front,Eye) = Front.x·eyeX + Front.y·eyeY + Front.z·eyeZ

3. 投影矩阵Projection Matrix

3.1 正交投影

  • 方法: Matrix.orthoM(float[] m, int mOffset, float left, float right, float bottom, float top, float near, float far)
  • 参数说明:
    left, right: 近平面左右边界坐标
    bottom, top: 近平面下上边界坐标
    near, far: 近平面和远平面到相机的距离
  • 取值范围与建议:
    left < right, bottom < top, near < far
    nearfar通常为正值,但某些实现中可以为负值
    坐标范围取决于场景大小,常见如(-10,10,-10,10,1,100)
  • 公式:
[ 2/(right-left)      0                 0              -(right+left)/(right-left) ]   [ x ]   [ 2x/(right-left) - (right+left)/(right-left) ]
[ 0            2/(top-bottom)           0              -(top+bottom)/(top-bottom) ] × [ y ] = [ 2y/(top-bottom) - (top+bottom)/(top-bottom) ]
[ 0                   0           -2/(far-near)        -(far+near)/(far-near)     ]   [ z ]   [ -2z/(far-near) - (far+near)/(far-near)      ]
[ 0                   0                 0                        1                 ]   [ 1 ]   [                  1                          ]
  • 特点:
    • 保持物体原始比例,不会因距离而变形
    • 视锥体是长方体形状
    • 适合2D绘制和UI界面

3.2 透视投影

  • 方法: Matrix.frustumM(float[] m, int mOffset, float left, float right, float bottom, float top, float near, float far)
  • 参数说明:
    left, right: 近平面左右边界坐标
    bottom, top: 近平面上下边界坐标
    near: 近平面距离,必须为正值
    far: 远平面距离,必须为正值且大于near
  • 取值范围与建议:
    left=-right, bottom=-top
    near不宜过小,通常0.1-1.0
    far通常10-1000,取决于场景大小
  • 公式:
[ 2*near/(right-left)  0                  (right+left)/(right-left)  0                    ]   [ x ]
[ 0                    2*near/(top-bottom) (top+bottom)/(top-bottom)  0                    ] × [ y ]
[ 0                    0                   -(far+near)/(far-near)     -2*far*near/(far-near) ]   [ z ]
[ 0                    0                   -1                         0                    ]   [ 1 ]
  • 结果:
[ 2*near*x/(right-left) + (right+left)*z/(right-left)                            ]
[ 2*near*y/(top-bottom) + (top+bottom)*z/(top-bottom)                            ]
[ -(far+near)*z/(far-near) - 2*far*near/(far-near)                               ]
[ -z                                                                              ]
  • 特点:
    • 模拟人眼视觉,远处物体显得更小
    • 适合大多数3D场景渲染

三、MVP矩阵组合计算

  • 方法: Matrix.multiplyMM()
  • 计算流程:
// 模型视图矩阵Model x View = 视图矩阵View × 模型矩阵Model
Matrix.multiplyMM(mvpMatrix, 0, viewMatrix, 0, modelMatrix, 0)

// MVP矩阵 = 投影矩阵Projection × 模型视图矩阵Model View = Projection × View × Model
Matrix.multiplyMM(mvpMatrix, 0, projectionMatrix, 0, mvpMatrix, 0)

// 最终坐标变换
// [x', y', z', w'] = MVP × [x, y, z, 1]
  • 注意事项:
  • OpenGL中矩阵乘法是右结合的,从右到左计算
  • 变换顺序非常重要: 先模型变换,再视图变换,最后投影变换
  • 最终变换结果应用于顶点着色器的gl_Position

http://www.kler.cn/a/613882.html

相关文章:

  • 信息学奥赛一本通 1514:【例 2】最大半连通子图 | 洛谷 P2272 [ZJOI2007] 最大半连通子图
  • Emacs 折腾日记(二十)——修改emacs的一些默认行为
  • 【C++项目实战】:基于正倒排索引的Boost搜索引擎(1)
  • s1: Simple test-time scaling 【论文阅读笔记】
  • PPTP、L2TP 和 IPSec
  • PyTorch 分布式训练(Distributed Data Parallel, DDP)简介
  • 在IDEA中快速注释所有console.log
  • Taro创建微信小程序项目 第一步搭建项目
  • 掌握!Postman 设置 Bearer Token 的完整指南
  • 3d pose 指标和数据集
  • 【tips】微信小程序wxs 注意
  • WHAT - 程序员英语之美式发音学习系列(五)
  • 【华三】华三模拟器HCL防火墙、AC和交换机的Web登入
  • 06-SpringBoot3入门-常见注解(简介)
  • 基于HTML5和CSS3实现3D旋转相册效果
  • 力扣hot100二刷——动态规划
  • uni-app踩坑记录【图片先压缩再上传】
  • Oracle 数据库同步至 GaussDB问题及解决方案
  • uv:现代 Python 项目管理的高效助手
  • 简单介绍一下Unity中的ScriptableObject