unity常用变换计算

这篇博客详细介绍了Unity中的变换计算,包括向量、四元数、矩阵、Transform组件、射线、相机的操作,以及如何利用手机陀螺仪计算矩阵。内容涵盖向量的点积和叉积、四元数旋转、矩阵变换、Transform坐标转换、射线检测和相机视野计算等,对于Unity游戏开发非常实用。
摘要由CSDN通过智能技术生成

unity变换计算

向量

Vector3.up 是 y 轴正向 , Vector3.right 是 x 轴正向,Vector3.forward 是 z 轴正向

  • 点积(Dot)
    Vector3.Dot(a,b)

  • 叉积(Cross)
    Vector3.Cross(a,b)

  • 判断向量垂直
    Vector3.Dot(a,b)=0 >0表示向量夹角<90,<0表示向量夹角>90

  • 计算2个向量的夹角

	// 获得夹角
	float angle = Vector3.Angle(fromVector, toVector);
	// 获得法线向量
	Vector3 normal = Vector3.Cross(fromVector, toVector);
	//	获得夹角的正负值
	angle *= Mathf.Sign(Vector3.Dot(normal, upVector));

四元数操作

  • 欧拉角转换
    // 绕y轴旋转 degree 度
    Quaternion rot = Quaternion.Euler(0, degree, 0);
    等价于
    Quaternion q = Quaternion.AngleAxis(degree, Vector3.up);

  • 旋转叠加
    q=qa*qb; // 顺序是有影响的,先旋转qa再旋转qb

  • 相乘顺序
    q=qa * qb * qc=( qa * qb ) * qc=qa * ( qb * qc )

  • 相乘求反
    ( qa * qb ).inverse = qb.inverse * qa.inverse;

  • *=的运算顺序
    a *= b * c; // 等价于 a = a * ( b * c );

  • 向量旋转
    通过 rotation 获得当前向上向量,本质上就是把向上向量旋转 rotation
    Vector3 newUp = rotation * Vector3.up;
    其它方向也是一样的
    可以直接参考 Transform.up

  • 旋转到向量
    比如向上旋转到 newUp ,刚好是上面向量旋转的逆操作,则旋转角度为
    Quaternion q = Quaternion.FromToRotation(Vector3.up, newUp);

  • 通过2个方向获得当前旋转
    比如 通过 forward 和 upwards 确定方向

	//	这里 forward 和 upward 不要求垂直,这里保证计算出的方向 forward 对齐 
	//	因为实际上是 left = upward*forward,用 forward 和 left 来计算旋转
	//	Z 轴将与forward对齐,X 轴与 forward 和 upwards 的差积对齐
	Quaternion rotation = Quaternion.LookRotation(forward, upward);
	
	//	如果要保证 upward 对齐,有3种方法(摘自 QuaternionUtil)
	//      1. 把要精准对齐的当成 forward,另一个当成 upward,用 Quaternion.LookRotation 算出方向后,再把坐标轴还原
	public static Quaternion LookRotationYZ(Vector3 up, Vector3 forward)
	{
   
		return Quaternion.LookRotation(up, -forward) * Quaternion.AngleAxis(90, Vector3.right);
	}
	//      2. 用叉积计算出精准的 forward, 再用 Quaternion.LookRotation 计算出方向
	public static Quaternion LookRotationYZ2(Vector3 up, Vector3 forward)
	{
   
		Vector3 left = Vector3.Cross(up, forward);
		Vector3 forwardNew = Vector3.Cross(left, up);       //	重新计算出 forward
		return Quaternion.LookRotation(forwardNew, up);
	}
	//      3. 用平面投影计算出精准的 forward, 再用 Quaternion.LookRotation 计算出方向,参考 LookRotationYZ3
	public static Quaternion LookRotationYZ3(Vector3 up, Vector3 forward)
	{
   
		Plane plane = new Plane(up, Vector3.zero);
		Vector3 forwardNew = plane.ClosestPointOnPlane(forward);	//  forward 在 up 为法线的平面上的投影
		return Quaternion.LookRotation(forwardNew, up);
	}

	//	应用举例,比如 场景确定好坐标和向上方向后,要朝向相机
	void AdjustSceneTransform(Transform sceneTransfrom, Vector3 pos, Vector3 upword, Vector3 cameraPos )
    {
   
        Vector3 forward = pos - cameraPos;
        Vector3 left = Vector3.Cross(upword, forward);
        forward = Vector3.Cross(left, upword);
        Quaternion rotation = Quaternion.LookRotation(forward, upword);
        sceneTransfrom.position = pos;
        sceneTransfrom.rotation = rotation;
    }

矩阵操作

  • M行N列矩阵的存储(展开成一维数组)有2种方式:

    1. 行优先: 先存储第一行,再存储第二行,依次类推,i行j列元素=i*N+j
    2. 列优先: 先存储第一列,再存储第二列,依次类推,i行j列元素=j*M+i
      2种存储方式互为转置关系: M行优先=M列优先.transpose
  • unity 采用的是方案2,也就是列优先,这点在 Matrix4x4 文档中有说明
    平移存储在最后一列,因此跟 Vector4 相乘时是 M*V ,也就是M在前,V在后,V写成4行1列

  • 相乘
    m = a * b; // 先进行 a 变换再进行 b 变换

  • 相乘求逆
    (a * b)-1 = b-1 * a-1

  • TRS
    m = Matrix4x4.TRS(t,r,s) = Matrix4x4.Translate§ * Matrix4x4.Rotate® * Matrix4x4.Scale(s);
    也就是先平移再旋转最后缩放

  • 从矩阵获得旋转
    直接获取 Quaternion q = m.rotation;
    参考 OpenCVForUnity\org\opencv\unity\ARUtils.cs
    Vector3 forward = new Vector3(m.02,m.12,m.22);
    Vector3 upwards = new Vector3(m.01,m.11,m.21);
    Quaternion q = Quaternion.LookRotation(forward, upwards);

  • 矩阵和Pose的互转
    Matrix4x4 m = Matrix4x4.TRS(pose.position,pose.rotation, Vector3.one); // pose转矩阵
    pose.position = new Vector3(m.03, m.13, m.23);
    pose.rotation = m.rotation;

  • 变换坐标点
    pos1 = matrix.MultiplyPoint3x4(pos); // 对坐标进行变换,等价于 matrix * new Vector4(pos.x,pos.y,pos.z,1)
    // 只能用于普通的 TRS 矩阵,也就是最后一行是 0,0,0,1 , 不能用于投影矩阵
    pos1 = matrix.MultiplyPoint(pos); // 对坐标进行变换,并归一化,适用于投影矩阵,普通 TRS 也能用,但可以用速度更快的 MultiplyPoint3x4
    pos1 = matrix * new Vector4(pos.x,pos.y,pos.z,1); // 相乘,效果同 MultiplyPoint3x4,不会进行归

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值