辅助资料unity

Unity中的空间转换矩阵构造

2019-05-29  本文已影响7人  最怕认真
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class MatrixPoint : MonoBehaviour {

    Matrix4x4 CreateMatrix()
    {
        Matrix4x4 matrix = new Matrix4x4();
        matrix.SetRow(0, new Vector4(transform.right.x, transform.up.x, transform.forward.x, transform.position.x));
        matrix.SetRow(1, new Vector4(transform.right.y, transform.up.y, transform.forward.y, transform.position.y));
        matrix.SetRow(2, new Vector4(transform.right.z, transform.up.z, transform.forward.z, transform.position.z));
        matrix.SetRow(3, new Vector4(0, 0, 0, 1));
        return matrix;
    }

    List<Vector3> TestPoints()
    {
        var p1 = Vector3.zero;
        var p2 = p1 + Vector3.right;
        var p3 = p2 + Vector3.up;
        var p4 = p1 + Vector3.up;
        List<Vector3> points = new List<Vector3>()
        {
            p1,p2,p3,p4
        };
        return points;
    }

    void DrawPoints(List<Vector3> points,Color color)
    {
        Gizmos.color = color;
        for (int i = 0; i < points.Count; i++)
        {
            Gizmos.DrawSphere(points[i], 0.01f);
            if (i != points.Count - 1)
                Gizmos.DrawLine(points[i], points[i + 1]);
        }
    }

    private void OnDrawGizmos()
    {
       
            var matrix = CreateMatrix();
            var testPoints = TestPoints();
            DrawPoints(testPoints, Color.red);

            List<Vector3> newPoints = new List<Vector3>();
            testPoints.ForEach(pt => newPoints.Add(matrix.MultiplyPoint(pt)));

            DrawPoints(newPoints, Color.blue);
       
    }

}

image.png

在场景中创建一个物体,然后将脚本挂载到该物体上,就会将世界坐标系下的点转换到物体本地坐标系下的位置。


这里主要的知识点是如何构造这个变化矩阵,也就是这段代码

 Matrix4x4 CreateMatrix()
    {
        Matrix4x4 matrix = new Matrix4x4();
        matrix.SetRow(0, new Vector4(transform.right.x, transform.up.x, transform.forward.x, transform.position.x));
        matrix.SetRow(1, new Vector4(transform.right.y, transform.up.y, transform.forward.y, transform.position.y));
        matrix.SetRow(2, new Vector4(transform.right.z, transform.up.z, transform.forward.z, transform.position.z));
        matrix.SetRow(3, new Vector4(0, 0, 0, 1));
        return matrix;
    }

关于unity中矩阵的图文讲解,这里有一篇文章很不错,可以查看,本文也借用了其中一些图片。

我们先回想下矩阵的计算规则


image.png

图示的非常清楚了,就是用前矩阵的和后矩阵的对应元素相乘然后累加。

那么为什么空间坐标的转换能用矩阵来表示呢?又应该如何表示呢?

image.png

我们先以二维空间的坐标转换为例。
wi,wj为w坐标系下的一组基,也就是我们所说的x和y坐标
li,lj为l坐标系下的一组基
在w坐标系下的wp,要转换到L坐标系下,并用w坐标系下的wi和wj来表示它。
很容易理解的是
lp = Lo + (u*Li,v*Lj)
我们把后半部分(uLi,vLj)换个写法
(u*Li,v*Lj) = u*(Li.x,Li.y),v*(Lj.x,Lj.y)=(u*Li.x+v*Lj.x , u*Li.y+v*Lj.y)
这个写法,似乎不太直观,不如这样,我们搞点新花样
把uv拿出来写成一列,变成这样

image.png
然后逗号左边的u*Li.x+v*Lj.x除去uv后剩下的Li.x+Lj.x也搞个新花样,变成这样
image.png
然后再做个规定,下面图片作用上面图片,就按照u*Li.x+v*Lj.x的规则来计算,没错,这就是矩阵的由来(我猜想的,史称认真的猜想)
那么逗号左右加起来应该是
image.png
整个lp-Lo就可以表示成
图3.png
那么lp就应该等于Lo+图3
有没有办法把Lo也用这种方法表示下,有的
image.png

所以整个lp就可以用图3来表示了。


那么扩展到3d中

 Matrix4x4 CreateMatrix()
    {
        Matrix4x4 matrix = new Matrix4x4();
        matrix.SetRow(0, new Vector4(transform.right.x, transform.up.x, transform.forward.x, transform.position.x));
        matrix.SetRow(1, new Vector4(transform.right.y, transform.up.y, transform.forward.y, transform.position.y));
        matrix.SetRow(2, new Vector4(transform.right.z, transform.up.z, transform.forward.z, transform.position.z));
        matrix.SetRow(3, new Vector4(0, 0, 0, 1));
        return matrix;
    }

这样来构建矩阵就很顺理成章了


上一篇下一篇

猜你喜欢

热点阅读