3D空间中的变换矩阵

3D 空间中的变换矩阵详解

在 3D 计算机图形学中,所有几何变换都可以通过 4×4 齐次变换矩阵 来表示。以下详细介绍各种变换矩阵及其原理。

核心变换矩阵

1. 单位矩阵(不变变换)

I=[1000010000100001] I = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} I=1000010000100001

2. 平移矩阵(Translation)

将点 p=[x,y,z,1]T\mathbf{p} = [x, y, z, 1]^Tp=[x,y,z,1]T 沿向量 t=[tx,ty,tz]\mathbf{t} = [t_x, t_y, t_z]t=[tx,ty,tz] 移动:

T=[100tx010ty001tz0001] T = \begin{bmatrix} 1 & 0 & 0 & t_x \\ 0 & 1 & 0 & t_y \\ 0 & 0 & 1 & t_z \\ 0 & 0 & 0 & 1 \end{bmatrix} T=100001000010txtytz1

变换后坐标:
p′=T⋅p=[x+tx,y+ty,z+tz,1]T p' = T \cdot p = [x+t_x, y+t_y, z+t_z, 1]^T p=Tp=[x+tx,y+ty,z+tz,1]T

T逆矩阵:将 (tx,ty,tz)(t_x,t_y,t_z)(tx,ty,tz) 取负

3. 缩放矩阵(Scaling)

沿坐标轴缩放,缩放因子 (sx,sy,sz)(s_x, s_y, s_z)(sx,sy,sz)

S=[sx0000sy0000sz00001] S = \begin{bmatrix} s_x & 0 & 0 & 0 \\ 0 & s_y & 0 & 0 \\ 0 & 0 & s_z & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} S=sx0000sy0000sz00001

特殊类型:

  • 均匀缩放sx=sy=szs_x = s_y = s_zsx=sy=sz
  • 镜像:某个分量为负(如 sx=−1s_x = -1sx=1
    逆矩阵:使用 (1/sx,1/sy,1/sz)(1/s_x,1/s_y,1/s_z)(1/sx,1/sy,1/sz)(假设因子不为0)。

4. 旋转矩阵(Rotation)

a) 绕坐标轴旋转
旋转轴矩阵
X轴Rx(θ)=[10000cos⁡θ−sin⁡θ00sin⁡θcos⁡θ00001]R_x(\theta) = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & \cos\theta & -\sin\theta & 0 \\ 0 & \sin\theta & \cos\theta & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}Rx(θ)=10000cosθsinθ00sinθcosθ00001
Y轴Ry(θ)=[cos⁡θ0sin⁡θ00100−sin⁡θ0cos⁡θ00001]R_y(\theta) = \begin{bmatrix} \cos\theta & 0 & \sin\theta & 0 \\ 0 & 1 & 0 & 0 \\ -\sin\theta & 0 & \cos\theta & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}Ry(θ)=cosθ0sinθ00100sinθ0cosθ00001
Z轴Rz(θ)=[cos⁡θ−sin⁡θ00sin⁡θcos⁡θ0000100001]R_z(\theta) = \begin{bmatrix} \cos\theta & -\sin\theta & 0 & 0 \\ \sin\theta & \cos\theta & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}Rz(θ)=cosθsinθ00sinθcosθ0000100001

旋转方向:右手坐标系中,逆时针为正方向(从旋转轴正向观察)

b) 绕任意轴旋转(Rodrigues公式)

绕单位向量 u=[ux,uy,uz]\mathbf{u} = [u_x, u_y, u_z]u=[ux,uy,uz] 旋转角度 θ\thetaθ

R(u,θ)=[cos⁡θ+ux2(1−cos⁡θ)uxuy(1−cos⁡θ)−uzsin⁡θuxuz(1−cos⁡θ)+uysin⁡θ0uyux(1−cos⁡θ)+uzsin⁡θcos⁡θ+uy2(1−cos⁡θ)uyuz(1−cos⁡θ)−uxsin⁡θ0uzux(1−cos⁡θ)−uysin⁡θuzuy(1−cos⁡θ)+uxsin⁡θcos⁡θ+uz2(1−cos⁡θ)00001] R(\mathbf{u}, \theta) = \begin{bmatrix} \cos\theta + u_x^2(1-\cos\theta) & u_xu_y(1-\cos\theta) - u_z\sin\theta & u_xu_z(1-\cos\theta) + u_y\sin\theta & 0 \\ u_yu_x(1-\cos\theta) + u_z\sin\theta & \cos\theta + u_y^2(1-\cos\theta) & u_yu_z(1-\cos\theta) - u_x\sin\theta & 0 \\ u_zu_x(1-\cos\theta) - u_y\sin\theta & u_zu_y(1-\cos\theta) + u_x\sin\theta & \cos\theta + u_z^2(1-\cos\theta) & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} R(u,θ)=cosθ+ux2(1cosθ)uyux(1cosθ)+uzsinθuzux(1cosθ)uysinθ0uxuy(1cosθ)uzsinθcosθ+uy2(1cosθ)uzuy(1cosθ)+uxsinθ0uxuz(1cosθ)+uysinθuyuz(1cosθ)uxsinθcosθ+uz2(1cosθ)00001

5. 组合变换矩阵

变换矩阵可以通过乘法组合。注意矩阵乘法的顺序非常重要(不满足交换律)。通常,变换按以下顺序应用:缩放 -> 旋转 -> 平移,即:
M=T⋅R⋅S M = T \cdot R \cdot S M=TRS
但是,如果以不同的顺序应用,结果会不同。

例如,先绕Y轴旋转90度,再沿X轴平移3个单位,与先平移后旋转的结果不同:
​​先旋转后平移​​:点会先旋转,然后沿世界坐标系的X轴平移。
​​先平移后旋转​​:点先在世界坐标系中沿X轴平移,然后旋转(此时点的位置已经改变,旋转后位置不同)。

注意顺序

  1. 缩放 (S)
  2. 旋转 ®
  3. 平移 (T)

这是因为矩阵乘法是 右乘结合p′=T⋅(R⋅(S⋅p)) \mathbf{p}' = T \cdot (R \cdot (S \cdot \mathbf{p})) p=T(R(Sp))

特殊变换类型

1. 剪切矩阵(Shear)

H=[1hxyhxz0hyx1hyz0hzxhzy100001] H = \begin{bmatrix} 1 & h_{xy} & h_{xz} & 0 \\ h_{yx} & 1 & h_{yz} & 0 \\ h_{zx} & h_{zy} & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} H=1hyxhzx0hxy1hzy0hxzhyz100001

2. 正交投影矩阵

向XY平面投影:
Portho=[1000010000000001] P_{\text{ortho}} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} Portho=1000010000000001

变换矩阵在编程中的实现

使用GLM(OpenGL Mathematics)库示例(两种写法)

  1. GLM函数叠加运算
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>// 初始化矩阵
glm::mat4 model = glm::mat4(1.0f); // 单位矩阵// 平移:沿X轴移动1.5单位
model = glm::translate(model, glm::vec3(1.5f, 0.0f, 0.0f));// 旋转:绕Z轴旋转90度
model = glm::rotate(model, glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f));// 缩放:Y轴放大2倍
model = glm::scale(model, glm::vec3(1.0f, 2.0f, 1.0f));

变换顺序很重要:矩阵乘法从右到左应用变换,所以上面代码的顺序实际上是先缩放,再旋转,最后平移。
在组合变换时,考虑使用逆序:先进行的变换在矩阵乘法中放在右边(后乘),后进行的变换放在左边(先乘)

2. 计算好各个变换矩阵后再相乘

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/transform.hpp>int main() {// 单位矩阵glm::mat4 identity = glm::mat4(1.0f);// 平移变换:沿X轴移动2个单位glm::mat4 translation = glm::translate(glm::mat4(1.0), glm::vec3(2.0f, 0.0f, 0.0f));// 缩放变换:Y轴扩大3倍glm::mat4 scaling = glm::scale(glm::mat4(1.0), glm::vec3(1.0f, 3.0f, 1.0f));// 旋转变换:绕Z轴旋转45度glm::mat4 rotation = glm::rotate(glm::mat4(1.0), glm::radians(45.0f), glm::vec3(0.0f, 0.0f, 1.0f));// 绕任意轴旋转:绕(1,1,0)旋转30度glm::vec3 axis = glm::normalize(glm::vec3(1.0f, 1.0f, 0.0f));glm::mat4 customRotation = glm::rotate(glm::mat4(1.0), glm::radians(30.0f), axis);// 组合变换:先缩放,再旋转,最后平移glm::mat4 composite = translation * rotation * scaling;// 应用变换到点glm::vec4 point(1.0f, 1.0f, 0.0f, 1.0f);glm::vec4 transformedPoint = composite * point;return 0;
}

手动实现矩阵类

class Matrix4f {
public:float m[4][4];Matrix4f() { /* 初始化为单位矩阵 */ }static Matrix4f translate(float tx, float ty, float tz) {Matrix4f m;m.m[0][3] = tx;m.m[1][3] = ty;m.m[2][3] = tz;return m;}static Matrix4f scale(float sx, float sy, float sz) {Matrix4f m;m.m[0][0] = sx;m.m[1][1] = sy;m.m[2][2] = sz;return m;}static Matrix4f rotateX(float angle) {float rad = angle * M_PI/180.0;float c = cos(rad);float s = sin(rad);Matrix4f m;m.m[1][1] = c; m.m[1][2] = -s;m.m[2][1] = s; m.m[2][2] = c;return m;}Matrix4f operator*(const Matrix4f& right) const {// 矩阵乘法实现}Vec4f operator*(const Vec4f& v) const {// 矩阵向量乘法}
};

变换矩阵的性质与应用

  1. 齐次坐标

    • 3D点:[x, y, z, 1]ᵀ
    • 3D向量:[x, y, z, 0]ᵀ(防止被平移)
  2. 逆变换

    • 平移逆矩阵:$ T^{-1}(t_x, t_y, t_z) = T(-t_x, -t_y, -t_z) $
    • 缩放逆矩阵:$ S^{-1}(s_x, s_y, s_z) = S(1/s_x, 1/s_y, 1/s_z) $
    • 旋转逆矩阵:$ R^{-1} = R^T $(正交矩阵)
  3. 组合变换求逆
    组合变换的逆矩阵可以通过矩阵求逆得到。如果变换矩阵是正交的(纯旋转,不含缩放或错切),则转置就是逆矩阵。如果包含平移和缩放,则需要计算逆矩阵:

    (T⋅R⋅S)−1=S−1⋅R−1⋅T−1 (T \cdot R \cdot S)^{-1} = S^{-1} \cdot R^{-1} \cdot T^{-1} (TRS)1=S1R1T1
    其中:
    T −1 :将平移向量取负。
    R −1:旋转矩阵的转置(因为旋转矩阵正交)。
    S −1:缩放因子的倒数(假设非零)。

  4. 在变换链中的位置

    局部坐标 → 模型矩阵 → 世界坐标↓
    世界坐标 → 视图矩阵 → 观察坐标↓
    观察坐标 → 投影矩阵 → 裁剪坐标
    

可视化理解变换顺序

考虑一个点 P(0,1,0) 的变换过程:

原始位置: 0,1,0
缩放: 2倍Y轴
结果: 0,2,0
旋转: 绕Z轴90度
结果: -2,0,0
平移: X轴移动3单位
最终位置: 1,0,0
错误顺序
先平移: 3,1,0
后旋转: -1,3,0
结果不符

正确的矩阵乘法顺序:
Pfinal=[1003010000100001]⏟平移×[0−100100000100001]⏟旋转×[1000020000100001]⏟缩放×[0101] P_{\text{final}} = \underset{\text{平移}}{\underbrace{ \begin{bmatrix} 1 & 0 & 0 & 3 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} }} \times \underset{\text{旋转}}{\underbrace{ \begin{bmatrix} 0 & -1 & 0 & 0 \\ 1 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} }} \times \underset{\text{缩放}}{\underbrace{ \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 2 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} }} \times \begin{bmatrix} 0 \\ 1 \\ 0 \\ 1 \end{bmatrix} Pfinal=平移1000010000103001×旋转0100100000100001×缩放1000020000100001×0101

这些矩阵构成了 3D 图形学的基础,在 OpenGL、DirectX、Vulkan 等图形 API 以及 Unity、Unreal 等游戏引擎中广泛使用。掌握它们对于理解 3D 渲染管线至关重要。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/91477.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/91477.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

长连接(Long Connection)详解

一、长连接基本概念长连接&#xff08;也称为持久连接&#xff09;是指在一个TCP连接上可以连续发送多个HTTP请求/响应&#xff0c;而不是每次通信都建立新的连接。这是HTTP/1.1的默认行为&#xff0c;通过Connection: keep-alive头部实现。二、工作原理1. 传统短连接流程客户端…

【汇总】接口自动化测试 + 持续集成(文末视频演示)

技术栈&#xff1a;java testng httpclient allure fastjson jsonpath poi/yaml log4j 有建议请联系wx&#xff1a;ren168632201 java接口自动化系列(01)&#xff1a;自动化测试框架设计(入门版) java接口自动化系列(02)&#xff1a;测试数据文件设计(excel/yam) java接…

科研快报 |无人机+AI:广东防控基孔热背后的技术革命

Prism Path 科 研 快 报 CS跨学科顶尖期刊论文资讯 -NO.2025001- 人工智能在登革热预防、控制与管理中的作用&#xff1a;一项技术性叙述综述 The role of artificial intelligence for dengue prevention, control, and management: A technical narrative review 期刊…

常见的中间件漏洞

建议&#xff1a;启动下一个环境时&#xff0c;将上一个环境关闭&#xff0c;防止端口冲突和运行卡顿1.TomcatTomcat put方法任意文件写入漏洞Apache Tomcat 7.0.0 - 7.0.79 Apache Tomcat 8.5.19环境&#xff1a;cd vulhub-master/tomcat/CVE-2017-12615 docker-compose up -d…

7寸工业模组 XA070Y2-L01芯显科技详细参数资料

芯显7寸工业液晶屏 XA070Y2-L01 技术规格单 基础信息 项目 参数 制造商 芯显 型号 XA070Y2-L01 显示技术 a-Si TN TFT-LCD 应用场景 车载中控 / 工业HMI 屏幕尺寸 7.0英寸 机械结构 特性 指标 显示区域 152.4 91.44 mm 整机尺寸 165 104.09 9.1 mm 公差范围 0.5 mm 表面处理…

机器学习基础-numpy

一、相关知识点二、例子&#xff1a;import matplotlib.pyplot as plt import numpy as npplt.rcParams[font.sans-serif] [KaiTi] # 使用黑体 plt.rcParams[axes.unicode_minus] False # 解决负号显示问题math np.random.randint(low60,high100,size50) english np.rand…

Cockpit管理服务器

Cockpit 是一个开源工具&#xff0c;通过Web Console管理Linux服务器。部署 Cockpit[rootserver ~ 11:05:26]# yum -y install cockpit​[rootserver ~ 11:30:26]# systemctl enable cockpit.socket --nowCreated symlink from /etc/systemd/system/sockets.target.wants/cockp…

处理订单过期但支付成功的系统设计:平衡用户体验与业务规则

设计一个处理订单过期但用户支付成功的场景&#xff0c;需要平衡用户体验、系统一致性和业务规则。以下是一个系统化的设计方案&#xff0c;涵盖关键流程、异常处理和用户沟通&#xff1a;1. 场景分析 背景&#xff1a;用户在下单后&#xff0c;订单因超时而被标记为“过期”&a…

AI学习笔记三十三:基于Opencv的单目标跟踪

若该文为原创文章&#xff0c;转载请注明原文出处。一、功能介绍主要是想实现跟踪视频中的一个特定目标。使用了OpenCV库来实现视频中特定目标的跟踪。需要提供视频文件路径以及目标在第一帧中的位置坐标&#xff08;x, y, width, height&#xff09;&#xff0c;程序会自动跟踪…

第二篇:Three.js核心三要素:场景、相机、渲染器

第二篇&#xff1a;Three.js核心三要素&#xff1a;场景、相机、渲染器 引言 在Three.js的世界里&#xff0c;场景(Scene)、相机(Camera)和渲染器(Renderer)构成了最基础的"铁三角"。它们如同导演、摄像机和放映机&#xff0c;共同决定了3D内容的呈现方式。本篇将深入…

RagFlow本地源码部署(非Docker)

参考官方文档做个总结 1. 提前安装好uv pipx install uv pre-commit2. 下载源码&#xff1a; git clone https://github.com/infiniflow/ragflow.git cd ragflow/ uv sync --python 3.10 --all-extras # install RAGFlow dependent python modules uv run download_deps.py …

[免费]基于Python的招聘职位信息推荐系统(猎聘网数据分析与可视化)(Django+requests库)【论文+源码+SQL脚本】

大家好&#xff0c;我是python222_小锋老师&#xff0c;看到一个不错的基于Python的招聘职位信息推荐系统(猎聘网数据分析与可视化)(Djangorequests库)&#xff0c;分享下哈。 项目视频演示 【免费】基于Python的招聘职位信息推荐系统(猎聘网数据分析与可视化)(Django爬虫) P…

国产化PDF处理控件Spire.PDF教程:Java 提取 PDF 图片,高质量提取与图片过滤技巧

在处理包含图片的 PDF 文件时&#xff0c;例如扫描文档、产品手册或宣传资料&#xff0c;我们经常需要将其中的图像提取出来&#xff0c;用于保存、识别或再加工。E-iceblue旗下Spire系列产品&#xff0c;是文档处理领域的佼佼者&#xff0c;支持国产化信创。本文将介绍如何使用…

Cesium 快速入门(七)材质详解

Cesium 快速入门&#xff08;七&#xff09;材质详解 看过的知识不等于学会。唯有用心总结、系统记录&#xff0c;并通过温故知新反复实践&#xff0c;才能真正掌握一二 作为一名摸爬滚打三年的前端开发&#xff0c;开源社区给了我饭碗&#xff0c;我也将所学的知识体系回馈给大…

C++:结构体(Structure)

目录 第一性原理出发&#xff1a;我们要解决什么问题&#xff1f; 定义结构体&#xff08;Defining Structures&#xff09; 问题&#xff1a;名字太长怎么办&#xff1f; 如何定义结构体变量&#xff1f; 结构体的大小&#xff08;Size of Structures&#xff09; 初始化…

化学结构式解读指南:从基础认知到InDraw智能识别

中文名称&#xff1a;3-[2-(二甲基氨基)乙基]-1H-吲哚英文名称&#xff1a;3-[2-(dimethylamino)ethyl]-1H-indole分子式: C12H16N2分子量: 188.2740这是什么结构式&#xff1f;怎么绘制呢&#xff1f;可以用InDraw里的AI图像识别这个结构式&#xff0c;也可以手动绘图&#xf…

如何使用一台电脑adb调试多个Android设备

目录 一、临时断开其中一个设备连接 二、指定调试设备 总结 当我们使用Android调试工具调试多个设备&#xff0c;例如一开始使用adb连接了一台Android真机进行调试&#xff0c;此时又在Android studio中打开了一个模拟机&#xff0c;此时我们在adb命令窗口中使用adb命令的…

ChatGPT的下一站:从“答案引擎”到“思维教练”

摘要&#xff1a;我们正处在一个“万物皆可ChatGPT”的时代&#xff0c;但当它沦为最高效的“代码搬运工”和“作业速成器”时&#xff0c;我们得到的究竟是效率的提升还是思维的退化&#xff1f;本文深入探讨一个引人深思的概念——“导师模式”的AI。它不再直接提供答案&…

SpringBoot集成Flyway

SpringBoot集成Flyway_springboot flyway-CSDN博客 Flyway 本质上是一个开源的数据库迁移工具&#xff0c;它能够以自动化、可重复且可靠的方式管理数据库的变更。无论是小型项目还是大型企业级应用&#xff0c;Flyway 都能助力开发者轻松应对数据库架构的演进。它支持多种数据…

【实时Linux实战系列】实时图像处理应用开发

在当今快速发展的技术领域&#xff0c;实时图像处理应用在众多领域发挥着至关重要的作用。从自动驾驶汽车、工业自动化检测到医疗影像诊断&#xff0c;实时图像处理技术的应用场景无处不在。通过在实时Linux系统中开发图像处理应用&#xff0c;开发者能够充分利用Linux的稳定性…