Unity局部和世界坐标系相互转换的实现原理
创作时间:
作者:
@小白创作中心
Unity局部和世界坐标系相互转换的实现原理
引用
CSDN
1.
https://blog.csdn.net/ysn11111/article/details/144612663
在Unity引擎中,理解局部坐标系和世界坐标系之间的转换原理对于游戏开发至关重要。本文将从线性代数的基础知识出发,详细解释缩放、旋转和平移矩阵的构成规则,并通过代码示例展示如何实现坐标转换。
前期准备
知识点①:
Unity中需要遵守的设定:
- 我们约定变换顺序为:缩放->旋转->平移。
- 我们约定旋转的顺序为:Z->X->Y。
知识点②:
- 基础变换矩阵的构成规则:
- 平移矩阵的定义:
逆矩阵 - 旋转矩阵的定义:
绕X轴旋转
度: 绕Y轴旋转
度: 绕Z轴旋转
度:
因为旋转矩阵是正交矩阵,所以它的逆矩阵就是它的转置矩阵。
即:假设有旋转矩阵A,那么 - 缩放矩阵的定义:
逆矩阵
局部坐标转世界
我们需要明白一个概念,在3D空间中,假设有一个结点R存在一个子节点A,那么如果R就是坐标原点,A的局部坐标系就是世界坐标系。如果结点R存在旋转,平移等变换,那么A的局部坐标依旧不会变,R的变换会带动A的变换。那么最终的世界坐标满足关系式:
M代表R的变换矩阵,A代表R在原点时的世界坐标(即局部坐标),A'代表最终的世界坐标。
再根据知识点1,得到矩阵M=平移矩阵A×旋转矩阵B×缩放矩阵C
便有如下代码:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
public Transform targetTrans;
private void Start()
{
Vector4 startPos = new Vector4(targetTrans.localPosition.x, targetTrans.localPosition.y, targetTrans.localPosition.z, 1);
Matrix4x4 scaleMatrix = ScaleMatrix(transform.localScale.x, transform.localScale.y, transform.localScale.z);
Matrix4x4 rotateMatrix = RotateYMatrix(transform.eulerAngles.y)*RotateXMatrix(transform.eulerAngles.x)*RotateZMatrix(transform.eulerAngles.z);
Matrix4x4 translateMatrix = TranslateMatrix(transform.position.x, transform.position.y, transform.position.z);
//按照缩放->旋转(按照Z->X->Y顺序旋转)->平移的变换顺序
Vector4 resPos = translateMatrix * rotateMatrix * scaleMatrix * startPos;
Debug.Log(string.Format("局部坐标转世界坐标={0}",resPos));
Debug.Log(string.Format("调用UnityAPI的结果={0}",transform.TransformPoint(startPos)));
}
//缩放矩阵
private Matrix4x4 ScaleMatrix(float x,float y,float z)
{
Matrix4x4 targetMatrix = new Matrix4x4();
targetMatrix.m00 = x;
targetMatrix.m11 = y;
targetMatrix.m22 = z;
targetMatrix.m33 = 1;
return targetMatrix;
}
//旋转矩阵(X轴)
private Matrix4x4 RotateXMatrix(float angle)
{
Matrix4x4 targetMatrix = new Matrix4x4();
targetMatrix.m00 = 1;
targetMatrix.m11 = Mathf.Cos(angle * Mathf.Deg2Rad);
targetMatrix.m12 = -Mathf.Sin(angle * Mathf.Deg2Rad);
targetMatrix.m21 = Mathf.Sin(angle * Mathf.Deg2Rad);
targetMatrix.m22 = Mathf.Cos(angle * Mathf.Deg2Rad);
targetMatrix.m33 = 1;
return targetMatrix;
}
//旋转矩阵(Y轴)
private Matrix4x4 RotateYMatrix(float angle)
{
Matrix4x4 targetMatrix = new Matrix4x4();
targetMatrix.m00 = Mathf.Cos(angle * Mathf.Deg2Rad);
targetMatrix.m02 = Mathf.Sin(angle * Mathf.Deg2Rad);
targetMatrix.m11 = 1;
targetMatrix.m20 = -Mathf.Sin(angle * Mathf.Deg2Rad);
targetMatrix.m22 = Mathf.Cos(angle * Mathf.Deg2Rad);
targetMatrix.m33 = 1;
return targetMatrix;
}
//旋转矩阵(Z轴)
private Matrix4x4 RotateZMatrix(float angle)
{
Matrix4x4 targetMatrix = new Matrix4x4();
targetMatrix.m00 = Mathf.Cos(angle * Mathf.Deg2Rad);
targetMatrix.m01 = -Mathf.Sin(angle * Mathf.Deg2Rad);
targetMatrix.m10 = Mathf.Sin(angle * Mathf.Deg2Rad);
targetMatrix.m11 = Mathf.Cos(angle * Mathf.Deg2Rad);
targetMatrix.m22 = 1;
targetMatrix.m33 = 1;
return targetMatrix;
}
//平移矩阵
private Matrix4x4 TranslateMatrix(float x,float y,float z)
{
Matrix4x4 targetMatrix = new Matrix4x4();
targetMatrix.m03 = x;
targetMatrix.m13 = y;
targetMatrix.m23 = z;
targetMatrix.m00 = 1;
targetMatrix.m11 = 1;
targetMatrix.m22 = 1;
targetMatrix.m33 = 1;
return targetMatrix;
}
}
挂载脚本:
我们用了Unity自带的局部转世界的APITransform.TransformPoint进行结果对比,发现最终的计算结果是一样的(忽略第四个参数1.0,代表的含义是点)。
世界坐标转局部
由刚刚的
公式推导,其实可以得到:
即局部坐标=逆变换世界坐标
由上面的性质得到已知 矩阵*M=平移矩阵A×旋转矩阵B×缩放矩阵C,那么矩阵M的逆矩阵
矩阵A,B,C的逆矩阵都可以根据知识点2得到结果,最终就可以根据世界坐标和逆变换反推导局部坐标。
热门推荐
中医消化系统调理良方,常见方法解析
「放屁很臭」要看醫生嗎?放屁很臭的原因解析,教你利用四飲食習慣自我檢測
千年金矿变景区:遂昌金矿一日游攻略
肚包肉虽香,小心高脂高胆固醇!
健康生活+精准监测:高效怀孕全攻略
备孕神器大揭秘:叶酸、肌醇、DHEA谁才是怀孕率提升王?
籽多多教你如何缓解备孕焦虑
迎子方和启宫汤:台北市立联合医院助孕良方
先睹为快!揭秘新版人民币:纸币更“闪亮”、硬币更精美
双氯芬酸钠使用指南:心血管风险需警惕,这些人群禁用
双氯芬酸钠缓释片:镇痛消炎效果好,四类疼痛可缓解
闭经调理有妙招,中医智慧让你‘大姨妈’回归正常
74岁刘晓庆戴天价翡翠,眼凸嘴翘,双手像生冻疮 ,扭头脖子吓人
甘肃女子豪掷千万买下万亩荒地,17年后地里的宝贝让她年入2.7亿
甘草种植技术及亩收益
甘草种植土壤pH酸碱度和智能滴灌应用
楞严咒背后的故事:佛陀、阿难与文殊菩萨
从选购到开花:风信子冬季种植完全指南
春季风信子种植指南:土培水培双管齐下
一文掌握风信子种植要点,打造最美阳台花园
中国绿卡申请攻略:特殊贡献者的通关秘籍
杭州到金华自驾游攻略:美景美食全攻略
杭州到金华旅游打卡地推荐:双龙洞、横店影视城等你来探秘
揭秘发动机积碳最少转速, 牢记“金标准”, 让积碳远离你的爱车!
如何清理发动机积碳?
老冯教你在家做肚包肉:高压锅版简单易学
内蒙古肚包肉:用胃包裹的草原美味
广东肚包肉,地道美食探秘
登临沂蒙三景区:从百丈瀑布到世界最大山体雕刻
琅琊古城在临沂重现,沉浸式体验成亮点