【图形学】TA之路-矩阵应用平移-旋转-大小
矩阵应用:在 Unity 中,Transform 和矩阵之间的关系非常密切。Transform 组件主要用于描述和控制一个物体在三维空间中的位置、旋转和缩放,而这些操作背后实际上都是通过矩阵来实现的
1. Transform 组件与矩阵的关系
Transform 组件包含以下三个核心属性:
- Position:物体的位置。
- Rotation:物体的旋转(通常以四元数或欧拉角表示)。
- Scale:物体的缩放。
Unity 在计算一个物体在世界空间中的最终位置、旋转和缩放时,会将这些属性组合成一个 4x4 的变换矩阵。
2. 变换矩阵 (Transformation Matrix)
变换矩阵是一个 4x4 矩阵,它可以表示一个物体在三维空间中的所有变换(平移、旋转、缩放)。这个矩阵通常被称为世界矩阵(World Matrix)或模型矩阵(Model Matrix)。
在 Unity 中,这个矩阵由 Transform 的 localToWorldMatrix 属性表示,用于将物体的本地坐标转换到世界坐标系中。
3. Unity 中矩阵的运算过程
当 Unity 计算一个物体在场景中的最终位置时,会依次应用以下矩阵变换:
- 缩放矩阵:描述物体的缩放变换。
- 旋转矩阵:描述物体的旋转变换。
- 平移矩阵:描述物体的位置变换。
4. Transform 矩阵的实际应用
当 Unity 需要将一个物体的本地坐标转换为世界坐标时,它会使用 localToWorldMatrix 进行转换。相反,如果需要将世界坐标转换为物体的本地坐标,Unity 会使用 worldToLocalMatrix。
原理解析
当一个物体的位置、旋转、缩放分别为 {0, 0, 0}、{90, 90, 90} 和 {1, 1, 1} 时,它的变换矩阵代表了如何将物体从其本地坐标系变换到世界坐标系。
1. 平移矩阵(Translation Matrix)
位置为 {0, 0, 0},意味着物体位于世界坐标系的原点(没有平移)。因此,平移矩阵是一个单位矩阵:

平移公式

2. 旋转矩阵(Rotation Matrix)
旋转为 {90°, 90°, 90°},意味着物体在每个轴上都旋转了 90 度。这个旋转由三个矩阵(分别绕 X 轴、Y 轴、Z 轴的旋转)组合而成。
- 绕 X 轴旋转 90 度:

X轴旋转公式

- 绕 Y 轴旋转 90 度:

Y轴旋转公式

- 绕 Z 轴旋转 90 度:

Z轴旋转公式

最终的旋转矩阵是这些矩阵的乘积:
Rotation Matrix=Rotation Matrix (X)×Rotation Matrix (Y)×Rotation Matrix (Z)
3. 缩放矩阵(Scale Matrix)
缩放为 {1, 1, 1},意味着物体在所有方向上都没有缩放。缩放矩阵也是单位矩阵

缩放公式

4. 组合变换矩阵
最终的变换矩阵是平移、旋转和缩放矩阵的组合。顺序为缩放 -> 旋转 -> 平移,因此组合矩阵为:
Transformation Matrix=Translation Matrix×Rotation Matrix×Scale Matrix
源码示例(个人写的,基本是这原理吧)
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
namespace Ethan
{public class Matrix4x4{private float[,] elements;// 构造函数public Matrix4x4(){elements = new float[4, 4];}// 用于初始化的构造函数public Matrix4x4(float[,] elements){this.elements = elements;}// 单位矩阵public static Matrix4x4 Identity(){return new Matrix4x4(new float[,]{{1, 0, 0, 0},{0, 1, 0, 0},{0, 0, 1, 0},{0, 0, 0, 1}});}// 零矩阵public static Matrix4x4 Zero(){return new Matrix4x4(new float[4, 4]);}// 矩阵乘法public static Matrix4x4 operator *(Matrix4x4 a, Matrix4x4 b){Matrix4x4 result = Zero();for (int i = 0; i < 4; i++){for (int j = 0; j < 4; j++){result.elements[i, j] = 0;for (int k = 0; k < 4; k++){result.elements[i, j] += a.elements[i, k] * b.elements[k, j];}}}return result;}// 平移矩阵public static Matrix4x4 Translate(float x, float y, float z){return new Matrix4x4(new float[,]{{1, 0, 0, x},{0, 1, 0, y},{0, 0, 1, z},{0, 0, 0, 1}});}// 绕X轴旋转矩阵public static Matrix4x4 RotateX(float angle){float rad = Mathf.Deg2Rad * angle;return new Matrix4x4(new float[,]{{1, 0, 0, 0},{0, Mathf.Cos(rad), -Mathf.Sin(rad), 0},{0, Mathf.Sin(rad), Mathf.Cos(rad), 0},{0, 0, 0, 1}});}// 绕Y轴旋转矩阵public static Matrix4x4 RotateY(float angle){float rad = Mathf.Deg2Rad * angle;return new Matrix4x4(new float[,]{{Mathf.Cos(rad), 0, Mathf.Sin(rad), 0},{0, 1, 0, 0},{-Mathf.Sin(rad), 0, Mathf.Cos(rad), 0},{0, 0, 0, 1}});}// 绕Z轴旋转矩阵public static Matrix4x4 RotateZ(float angle){float rad = Mathf.Deg2Rad * angle;return new Matrix4x4(new float[,]{{Mathf.Cos(rad), -Mathf.Sin(rad), 0, 0},{Mathf.Sin(rad), Mathf.Cos(rad), 0, 0},{0, 0, 1, 0},{0, 0, 0, 1}});}// 缩放矩阵public static Matrix4x4 Scale(float x, float y, float z){return new Matrix4x4(new float[,]{{x, 0, 0, 0},{0, y, 0, 0},{0, 0, z, 0},{0, 0, 0, 1}});}// 矩阵与向量相乘public static Vector3 MultiplyPoint(Matrix4x4 m, Vector3 point){float x = m.elements[0, 0] * point.x + m.elements[0, 1] * point.y + m.elements[0, 2] * point.z + m.elements[0, 3];float y = m.elements[1, 0] * point.x + m.elements[1, 1] * point.y + m.elements[1, 2] * point.z + m.elements[1, 3];float z = m.elements[2, 0] * point.x + m.elements[2, 1] * point.y + m.elements[2, 2] * point.z + m.elements[2, 3];return new Vector3(x, y, z);}// 显示矩阵内容public override string ToString(){string result = "";for (int i = 0; i < 4; i++){for (int j = 0; j < 4; j++){result += elements[i, j] + "\t";}result += "\n";}return result;}}
}
调用示例
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Vector3 = Ethan.Vector3;
using Matrix4x4 = Ethan.Matrix4x4;
public class Game : MonoBehaviour
{void Start(){// 创建变换矩阵Matrix4x4 rotation = Matrix4x4.RotateY(45); // 绕Y轴旋转45度Matrix4x4 translation = Matrix4x4.Translate(10, 0, 5); // 平移Matrix4x4 scale = Matrix4x4.Scale(2, 2, 2); // 缩放// 组合变换Matrix4x4 transformation = translation * rotation * scale;// 应用到一个点Vector3 originalPoint = new Vector3(1, 1, 1);Vector3 transformedPoint = Matrix4x4.MultiplyPoint(transformation, originalPoint);// 输出结果Debug.Log("初始点: " + originalPoint);Debug.Log("转换点: " + transformedPoint);Debug.Log("变换矩阵:\n" + transformation);}}
相关文章:
【图形学】TA之路-矩阵应用平移-旋转-大小
矩阵应用:在 Unity 中,Transform 和矩阵之间的关系非常密切。Transform 组件主要用于描述和控制一个物体在三维空间中的位置、旋转和缩放,而这些操作背后实际上都是通过矩阵来实现的 1. Transform 组件与矩阵的关系 Transform 组件包含以下…...
Spring 循环依赖解决方案
文章目录 1. 循环依赖的产生2. 循环依赖的解决模型3. 基于setter/Autowired 的循环依赖1_编写测试代码2_初始化 Cat3_初始化 Person4_ 回到 Cat 的创建流程5_小结 4. 基于构造方法的循环依赖5. 基于原型 Bean 的循环依赖6. 引人AOP的额外设计7. 总结 IOC 容器初始化bean对象的逻…...
可视化大屏:如何get到领导心目中的“科技感”?
你如果问领导可视化大屏需要什么风格的,领导大概率说科技感的,然后你就去做了,结果被劈了一顿,什么原因?因为你没有get到领导心目中描述的科技感。 一、为什么都喜欢科技感 科技感在可视化大屏设计中具有以下好处&am…...
基于Python的金融数据采集与分析的设计与实现
基于Python的金融数据采集与分析的设计与实现 “Design and Implementation of Financial Data Collection and Analysis based on Python” 完整下载链接:基于Python的金融数据采集与分析的设计与实现 文章目录 基于Python的金融数据采集与分析的设计与实现摘要第一章 绪论1…...
使用Sanic和SSE实现实时股票行情推送
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storm…...
redis散列若干记录
字典 redis本身使用字典结构管理数据 redis使用hash表实现字典结构 使用了什么hash算法 使用SipHash算法,该算法能有效防止Hash表碰撞,并有不错的性能 hash冲突怎么解决 使用链表法解决hash冲突 hash表如何扩容 渐进式扩容,不会引起线程长期阻…...
Java面试八股之什么是STOMP协议
什么是STOMP协议 STOMP(Simple Text Oriented Messaging Protocol)是一种为消息队列和事件驱动架构设计的轻量级协议,主要用于在消息中间件之间进行消息交换。它的设计原则是简单、跨平台和易于实现,这使得STOMP成为许多实时应用…...
【自用】Python爬虫学习(一):爬虫基础与四个简单案例
Python爬虫学习(一) 基础知识四个简单的爬虫案列1.使用urlopen获取百度首页并保存2.获取某翻译单词翻译候选结果3.获取某网页中的书名与价格4.获取某瓣排名前250的电影名称 基础知识 对于一个网页,浏览器右键可以查看页面源代码,…...
[python]uiautomation.WindowControl函数用法
Python UIAutomation 窗口控件 介绍 在本文中,我们将探讨Python UIAutomation库以及如何使用它来控制和自动化Windows应用程序。我们将介绍UIAutomation的基础知识及其功能,并提供代码示例来演示其用法。 什么是UI自动化? UIAutomation是一个…...
学习记录第二十七天
进程 wait函数 功能 等待子进程结束:父进程调用wait函数后,会暂停执行,直到它的某个子进程结束。收集子进程状态:当子进程结束时,wait函数会返回子进程的终止状态,包括是正常终止还是被信号终止等信息。…...
servlet的执行顺序
执行的时候Tomcat先初始化 然后调用 server 根据server来回调请求方式下面会追入源码解释 package com.haogu.servlet;import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.…...
Go语言 类封装和绑定方法
本篇文章主要内容为Go语言类相关操作:封装和绑定方法介绍及示例。 目录 封装 绑定方法 类方法形参 指针形参 设置类方法参数 指针与非指针区别 总结 封装 go语言支持类的操作,但是没有class关键字,使用struct来模拟类。 示例如下&am…...
DirectShow过滤器开发-写WAV音频文件过滤器
下载本过滤器DLL 本过滤器将PCM音频流,或ADPCM,IEEE_FLOAT,ALAW,MULAW,GSM610音频流写入WAV音频文件。 写WAV音频文件过滤器信息 过滤器名称:写WAV 过滤器GUID:{CF704A9C-0C67-4712-BA33-DD0A…...
php根据截止时间计算剩余的时间,并且在剩余时间不足1天时仅显示小时数
//获取政策库文章public function getIndexZckList(){$fl_id = input(fl_id);if(empty(...
Docker最佳实践进阶(一):Dockerfile介绍使用
大家好,上一个系列我们使用docker安装了一系列的基础服务,但在实际开发过程中这样一个个的安装以及繁杂命令不仅仅浪费时间,更是容易遗忘,下面我们进行Docker的进阶教程,帮助我们更快速的部署和演示项目。 一、什么是Dockerfile? Dockerfile 是一个文本文件,其中包含了…...
Anything in Any Scene:无缝融入任何场景,实现逼真视频对象插入技术
人工智能咨询培训老师叶梓 转载标明出处 现实世界的视频捕获虽然因其真实性而宝贵,但常常受限于长尾分布的问题,即常见场景过度呈现,而关键的罕见场景却鲜有记录。这导致了所谓的"分布外问题",在模拟复杂环境光线、几何…...
安卓开发中的AppCompat框架|安卓系统|安卓应用|兼容性|UI组件|核心组件|ActionBar|Fragment|最佳实践|框架|移动开发|移动应用
目录 1. 什么是AppCompat框架 1.1 AppCompat的起源 1.2 AppCompat的重要性 2. AppCompat框架的核心组件 2.1 AppCompatActivity 2.2 AppCompat主题 2.3 AppCompat Widgets 3. 在项目中使用AppCompat框架 3.1 添加依赖项 3.2 应用AppCompat主题 4. AppCompat的高级功…...
React使用useRef ts 报错
最近在写自己的React项目,我在使用useRef钩子函数的时候发现 TS2322: Type MutableRefObject<HTMLDivElement | undefined> is not assignable to type LegacyRef<HTMLDivElement> | undefined Type MutableRefObject<HTMLDivElement | undefined&g…...
python-信息交互-pyautogui
python-信息交互-pyautogui 一: pyautogui1> waht?2> 功能分类3> 概念及作用二: 通用功能1> function all2> function 注释三: 鼠标控制1> mouse functions2> mouse functions demo3> mouse drag demo四: keyboard控制1> keyboard functions2> …...
flink1.18 编译遇到的问题
1. flink-runtime-web编译失败 源码编译时一直卡在 [INFO] Running ‘npm ci --cache-max0 --no-save’ in 处理方法: 修改flink-runtime-web/pom.xml文件 将<arguments>ci --cache-max0 --no-save ${npm.proxy}</arguments> 替换为:<a…...
Google Translate PHP测试驱动开发:确保翻译质量的最佳实践指南
Google Translate PHP测试驱动开发:确保翻译质量的最佳实践指南 【免费下载链接】google-translate-php 🔤 Free Google Translate API PHP Package. Translates totally free of charge. 项目地址: https://gitcode.com/gh_mirrors/go/google-transla…...
docker-maven-plugin 源码解析:深入理解插件架构与实现原理
docker-maven-plugin 源码解析:深入理解插件架构与实现原理 【免费下载链接】docker-maven-plugin Maven plugin for running and creating Docker images 项目地址: https://gitcode.com/gh_mirrors/doc/docker-maven-plugin 一、插件核心架构概览 docker-…...
物理 AI 为什么离不开边缘计算?
过去两年,AI 给人的印象基本是一回事——一个对话框,一个输入框。你打字它打字,你上传它分析,AI 安静地待在屏幕里,处理着一切关于文字、图像、代码的事情。行业的注意力也都跟着堆在那一头。云厂商抢算力,…...
Java版Dify SDK:简化LLM应用开发,提升Java生态集成效率
1. 项目概述:为什么我们需要一个Java版的Dify SDK?如果你正在用Java构建一个需要集成大语言模型能力的应用,比如一个智能客服系统、一个文档分析工具,或者一个创意写作助手,你很可能听说过Dify。Dify作为一个开源的LLM…...
2026AI大模型API中转服务实测:多平台全方位对比,探寻最适配开发者的优质之选
跨国网络延迟、复杂的支付方式以及分散的接口协议,使得开发者在调用AI大模型API时体验欠佳。而智能中转平台的出现,能让这一切变得像调用本地服务一样轻松。API中转平台能够一站式解决国内外主流AI模型在价格差异、网络连通性以及支付方式等方面的问题。…...
互联网大厂 Java 求职者的面试:Spring Boot 的核心与微服务应用
互联网大厂 Java 求职之路:面试官的严肃与程序员燕双非的搞笑 在当今快速发展的互联网行业,Java 开发者的面试显得尤为重要。以下是一次精彩的面试场景,面试官与搞笑程序员燕双非之间的对话,展示了技术与幽默的完美结合。第一轮提…...
【图像去噪】基于自适应掩码和稀疏表示的自监督图像去噪研究(含PSNR)附Matlab代码
✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、程序设计科研仿真。🍎完整代码获取 定制创新 论文复现点击:Matlab科研工作室👇 关注我领取海量matlab电子书和数学建模资料 dz…...
基于Vue.js与AI对话的智能思维导图生成器开发实践
1. 项目概述:一个能“对话”的思维导图生成器最近在整理项目文档和梳理学习笔记时,我总感觉传统的思维导图工具少了点什么。要么是手动拖拽节点太繁琐,打断了思考的连贯性;要么是生成的导图结构僵化,难以体现思考的动态…...
你的微信聊天记录被加密了?用这个开源工具轻松解密!
你的微信聊天记录被加密了?用这个开源工具轻松解密! 【免费下载链接】WechatDecrypt 微信消息解密工具 项目地址: https://gitcode.com/gh_mirrors/we/WechatDecrypt 你是否曾经想过备份微信聊天记录,却发现数据库文件无法打开&#x…...
酷安UWP桌面版:在Windows上体验酷安社区的最佳指南
酷安UWP桌面版:在Windows上体验酷安社区的最佳指南 【免费下载链接】Coolapk-UWP 一个基于 UWP 平台的第三方酷安客户端 项目地址: https://gitcode.com/gh_mirrors/co/Coolapk-UWP 还在为手机屏幕太小而烦恼吗?想要在大屏幕上舒适浏览酷安社区内…...
