Unity矩阵平移旋转缩放Matrix4x4

Unity矩阵平移旋转缩放Matrix4x4

Unity中的矩阵(Matrix4x4)

最近在研究帧同步定点数物理系统中需要自定义定点数矩阵,所以在这里分享下基础的矩阵案例旋转、平移、缩放。(注意这里本文中的transform组件式基于unity浮点数的教程并非帧同步定点数)参考原文

创建自定义模型


参数可以参考我上图的参数,这里注意三个顶点是一个面,这里我上述的模型是一个三角形的面。

csharp 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Triangle : MonoBehaviour
{
    /// <summary>
    /// 网格
    /// </summary>
    Mesh mesh;
    
    /// <summary>
    /// 三角形顶点
    /// </summary>
    public Vector3[] vertices;

    /// <summary>
    /// 分配三角形顶点索引
    /// </summary>
    public int[] triangle;

    /// <summary>
    /// 材质球
    /// </summary>
    public Material mat;

    private void Start()
    {
        //实例化网格
        mesh = new Mesh();

        //分配顶点
        mesh.vertices = vertices;

        //分配三角形顶点索引
        mesh.triangles = triangle;

        //添加网格过滤器
        MeshFilter mf = gameObject.AddComponent<MeshFilter>();

        //网格赋值
        mf.mesh = mesh;
        
        //添加网格渲染器
        MeshRenderer mr = gameObject.AddComponent<MeshRenderer>();
        
        //材质赋值
        mr.materials[0] = mat;
    }
}

创建模型很简单我就不细讲了,看不懂的可以看上述的注释即可,直接黏贴也可。

平移矩阵

要做位移先搞明白矩阵中的哪几个索引值代表的坐标位置,如下图所示4x4矩阵

上图Tx,Ty,Tz为平邑的方向向量

这里可以自己做个测试,将transform的初始位置修改如下所示

代码如下

csharp 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyTransform : MonoBehaviour
{
    public Matrix4x4 matrix;

    // Start is called before the first frame update
    void Start()
    {
        matrix.SetTRS(transform.position,transform.rotation,transform.localScale);
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Q)) 
        {
            MyTranslate(new Vector3 (Random.Range(-5,5),Random.Range(-5,5), Random.Range(-5, 5)));
        }
    }

    public Vector4 v;

    /// <summary>
    /// 平移矩阵对象
    /// </summary>
    /// <param name="pos"></param>
    public void MyTranslate(Vector3 pos) 
    {
        //按照当前位置进行位移
        //v = new Vector4(transform.position.x,transform.position.y,transform.position.z,1);

        //按照原点进行位移
        v = new Vector4(0, 0, 0, 1);
        matrix = Matrix4x4.identity;

        //X、Y、Z移动因子
        matrix.m03 = pos.x;
        matrix.m13 = pos.y;
        matrix.m23 = pos.z;

        //矩阵位移操作
        v = matrix * v;

        transform.position = new Vector3(v.x, v.y, v.z);
    }
}

缩放矩阵

这个就是缩放矩阵,其中"Sx"、"Sy"、"Sz"就是各个轴上的缩放因子。缩放矩阵是矩阵表现物体大小变换的矩阵。如果缩放因子小于1,表现为物体缩小;如果大于1,则表现为物体扩大,如果等于1则不发生变化。

测试的话可以根据平移矩阵的测试方式修改scale来查看矩阵点对应值得变化

修改代码如下

csharp 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyTransform : MonoBehaviour
{
    public Matrix4x4 matrix;

    // Start is called before the first frame update
    void Start()
    {
        matrix.SetTRS(transform.position,transform.rotation,transform.localScale);
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Q)) 
        {
            MyTranslate(new Vector3 (Random.Range(-5,5),Random.Range(-5,5), Random.Range(-5, 5)));
        }
        if (Input.GetKeyDown(KeyCode.W)) 
        {
            int scale = Random.Range(-5,5);
            MyScale(new Vector3 (scale, scale, scale));
        }
    }

    public Vector4 v;

    /// <summary>
    /// 平移矩阵对象
    /// </summary>
    /// <param name="pos"></param>
    public void MyTranslate(Vector3 pos) 
    {
        //按照当前位置进行位移
        //v = new Vector4(transform.position.x,transform.position.y,transform.position.z,1);

        //按照原点进行位移
        v = new Vector4(0, 0, 0, 1);
        matrix = Matrix4x4.identity;

        //X、Y、Z移动因子
        matrix.m03 = pos.x;
        matrix.m13 = pos.y;
        matrix.m23 = pos.z;

        //矩阵位移操作
        v = matrix * v;

        transform.position = new Vector3(v.x, v.y, v.z);
    }

    /// <summary>
    /// 缩放矩阵对象
    /// </summary>
    /// <param name="scale"></param>
    public void MyScale(Vector3 scale) 
    {
        //设置当前对象大小
        //v = new Vector4(transform.localScale.x, transform.localScale.y, transform.localScale.z, 1);

        //按照原点进行位移
        v = new Vector4(1, 1, 1, 1);

        matrix = Matrix4x4.identity;

        //X、Y、Z缩放因子
        matrix.m00 = scale.x;
        matrix.m11 = scale.y;
        matrix.m22 = scale.z;

        //矩阵缩放操作
        v = matrix * v;

        transform.localScale = new Vector3(v.x, v.y, v.z);
    }
}

旋转矩阵

测试的话可以根据平移矩阵的测试方式修改Rotation来查看矩阵点对应值得变化

修改代码如下

csharp 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyTransform : MonoBehaviour
{
    public Matrix4x4 matrix;

    // Start is called before the first frame update
    void Start()
    {
        matrix.SetTRS(transform.position,transform.rotation,transform.localScale);
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Q)) 
        {
            MyTranslate(new Vector3 (Random.Range(-5,5),Random.Range(-5,5), Random.Range(-5, 5)));
        }
        if (Input.GetKeyDown(KeyCode.W)) 
        {
            int scale = Random.Range(-5,5);
            MyScale(new Vector3 (scale, scale, scale));
        }
        if (Input.GetKeyDown(KeyCode.A)) 
        {
            MyRotation( Axle.X,10f);
        }
        if (Input.GetKeyDown(KeyCode.S))
        {
            MyRotation(Axle.Y, 10f);
        }
        if (Input.GetKeyDown(KeyCode.D))
        {
            MyRotation(Axle.Z, 10f);
        }
    }

    public Vector4 v;

    /// <summary>
    /// 平移矩阵对象
    /// </summary>
    /// <param name="pos"></param>
    public void MyTranslate(Vector3 pos) 
    {
        //按照当前位置进行位移
        //v = new Vector4(transform.position.x,transform.position.y,transform.position.z,1);

        //按照原点进行位移
        v = new Vector4(0, 0, 0, 1);
        matrix = Matrix4x4.identity;

        //X、Y、Z移动因子
        matrix.m03 = pos.x;
        matrix.m13 = pos.y;
        matrix.m23 = pos.z;

        //矩阵位移操作
        v = matrix * v;

        transform.position = new Vector3(v.x, v.y, v.z);
    }

    /// <summary>
    /// 缩放矩阵对象
    /// </summary>
    /// <param name="scale"></param>
    public void MyScale(Vector3 scale) 
    {
        //设置当前对象大小
        //v = new Vector4(transform.localScale.x, transform.localScale.y, transform.localScale.z, 1);

        //按照原点进行位移
        v = new Vector4(1, 1, 1, 1);

        matrix = Matrix4x4.identity;

        //X、Y、Z缩放因子
        matrix.m00 = scale.x;
        matrix.m11 = scale.y;
        matrix.m22 = scale.z;

        //矩阵缩放操作
        v = matrix * v;

        transform.localScale = new Vector3(v.x, v.y, v.z);
    }

    public enum Axle { X, Y, Z}

    public void MyRotation(Axle axle,float angle) 
    {
        matrix = Matrix4x4.identity;

        //对应 X、Y、Z的旋转
        switch (axle)
        {
            case Axle.X:
                matrix.m11 = Mathf.Cos(angle * Mathf.Deg2Rad);
                matrix.m12 = -Mathf.Sin(angle * Mathf.Deg2Rad);
                matrix.m21 = Mathf.Sin(angle * Mathf.Deg2Rad);
                matrix.m22 = Mathf.Cos(angle * Mathf.Deg2Rad);
                break;
            case Axle.Y:
                matrix.m00 = Mathf.Cos(angle * Mathf.Deg2Rad);
                matrix.m02 = Mathf.Sin(angle * Mathf.Deg2Rad);
                matrix.m20 = -Mathf.Sin(angle * Mathf.Deg2Rad);
                matrix.m22 = Mathf.Cos(angle * Mathf.Deg2Rad);
                break;
            case Axle.Z:
                matrix.m00 = Mathf.Cos(angle * Mathf.Deg2Rad);
                matrix.m01 = -Mathf.Sin(angle * Mathf.Deg2Rad);
                matrix.m10 = Mathf.Sin(angle * Mathf.Deg2Rad);
                matrix.m11 = Mathf.Cos(angle * Mathf.Deg2Rad);
                break;
            default:
                break;
        }

        float qw = Mathf.Sqrt(1f + matrix.m00 + matrix.m11 + matrix.m22) / 2;
        float w = 4 * qw;
        float qx = (matrix.m21 - matrix.m12) / w;
        float qy = (matrix.m02 - matrix.m20) / w;
        float qz = (matrix.m10 - matrix.m01) / w;

        transform.rotation = new Quaternion(qx, qy, qz, qw);
    }

}

原文中有对应的小工具可以参考

相关推荐
天人合一peng1 小时前
unity 生成标记根据背景色变色为明显的颜色
unity·游戏引擎
魔士于安2 小时前
Unity 超市总动员 超市收银台 超市货架 超市购物手推车 超市常见商品
游戏·unity·游戏引擎·贴图·模型
CandyU22 小时前
Unity —— 数据持久化
unity·游戏引擎
zh路西法2 小时前
【Unity实现Oneshot胶卷显形】游戏窗口化与Win32API的使用
游戏·unity·游戏引擎
互联科技报3 小时前
2026年第一季度短视频矩阵视频混剪头部工具市场动态深度解析
人工智能·矩阵·音视频
一晌小贪欢3 小时前
第3节:从表格到矩阵——NumPy 高级索引与维度变换实战
线性代数·矩阵·numpy
图码4 小时前
矩阵数据结构入门指南:声明、初始化与基本操作
运维·数据结构·线性代数·算法·矩阵
凡情6 小时前
android隐私合规检测
android·unity
小贺儿开发7 小时前
Unity3D 本地 Stable Diffusion 文生图效果演示
人工智能·unity·stable diffusion·文生图·ai绘画·本地化
我是大聪明.7 小时前
Attention机制的数学本质:从Softmax到FlashAttention的演进
线性代数·矩阵