计算机图形数学相关的笔记 unity 的旋转、欧拉角、四元数、shader点旋转等 待更新。。

11 篇文章 0 订阅

旋转

矩阵旋转

求点p(x,y)在围绕原点o(0,0)旋转angle角度后,新的点p1的坐标位置(x1,y1)
使用旋转公式:
[ x 1 y 1 ] = [ c o s θ − s i n θ s i n θ c o s θ ] ∗ [ x y ] \begin{bmatrix} x^1 \\ y^1 \end{bmatrix} = \begin{bmatrix} cos\theta & -sin\theta \\ sin\theta & cos\theta \end{bmatrix} * \begin{bmatrix} x \\ y \end{bmatrix} [x1y1]=[cosθsinθsinθcosθ][xy]

//shader中的写法
//新x1坐标 = 原x坐标*cos(角度值) - 原y坐标*sin(角度值),角度值的取值区间是pi = 3.14, 相当于180度。该公式其实就是已知两直角边与夹角求第三遍长
x1 = x * cos(angle) - y * sin(angle);
y1 = x * sin(angle) + y * cos(angle);

欧拉旋转

欧拉旋转的原理是按照顺序旋转坐标轴而实现的,共有12种顺序:X-Y-Z X-Z-Y Y-X-Z Y-Z-X Z-X-Y Z-Y-X X-Y-X X-Z-X Y-X-Y Y-Z-Y Z-X-Z Z-Y-Z 。顺序的不同会导致旋转结果的巨大差异。

unity欧拉旋转使用的是 Y-X-Z的顺序
unity中的旋转
//世界坐标系的欧拉旋转  按照Z-X-Y的顺序依次旋转轴,即先绕z轴旋转90度,再按x轴旋转30度,最后按y轴旋转60度
cube.transform.Rotate(new Vector3(30f, 60f, 90f), Space.World);
//本地坐标系的欧拉旋转  按照Y-X-Z的顺序依次旋转轴,即先绕y轴旋转60度,再按x轴旋转30度,最后按z轴旋转90度
cube.transform.Rotate(new Vector3(30f, 60f, 90f), Space.Self);

四元旋转

用于旋转的四元数,每个分量的范围都在(-1,1);

unity中的四元数
//初始化rotation, 无旋转
myRotation = Quaternion.identity;
        
//四元数的逆, 返回一个相反的旋转
Debug.Log("相反的旋转为: "+ Quaternion.Inverse(target1.transform.rotation));
        
//返回欧拉角
Debug.Log("当前rotation的欧拉角为:" + target1.transform.eulerAngles);
        
//欧拉角转四元数
Debug.Log("欧拉角为0,90,0时,相对应的四元数是:" + Quaternion.Euler(new Vector3(0, 90, 0)));
//欧拉角转四元数并直接做旋转操作
target1.transform.rotation = Quaternion.Euler(new Vector3(0, 90, 0));
        
//返回两个旋转间的角度
float angle = Quaternion.Angle(target1.transform.rotation, Quaternion.FromToRotation(Vector3.up, transform.forward));
Debug.Log("两个旋转间的角度是: " + angle);
        
//以指定轴为旋转轴,旋转45度
Quaternion.AngleAxis(45, transform.up);
//在静止状态下,以transform.up为旋转轴顺时针旋转45度
target1.transform.rotation = Quaternion.AngleAxis(45, transform.up);
// *** 不管在静止状态下还是正在旋转中,以transform.up为旋转轴顺时针旋转45度
target1.transform.rotation = Quaternion.AngleAxis(45, transform.up) * target1.transform.rotation;
 
// 返回一个从Vector3.up到transform.forward方向旋转的四元数
target1.transform.rotation = Quaternion.FromToRotation(Vector3.up, target1.transform.forward);
 
//获取从target1到target2的方向
Vector3 dirction = target1.position - target2.position;
// 使用四元数,令target1看向target2
target1.transform.rotation = Quaternion.LookRotation(dirction);

void Update()
{
	//插值
	//已知间隔值为t
	float t = Time.deltaTime * 2f;
	//旋转四元数
	Quaternion q = Quaternion.Euler(new Vector3(0, 90, 0))
    //球面插值
    target1.transform.rotation = Quaternion.Slerp(target1.transform.rotation, q, t);
    //线性插值
    target1.transform.rotation = Quaternion.Lerp(target1.transform.rotation, q, t);
}
四元数转换
角转四元数

已知旋转轴向量(x, y, z)与旋转角度θ,求得四元数为q
q = (Xsinθ/2, Ysinθ/2, Zsinθ/2, cosθ/2) = ((X, Y, Z)sinθ/2, cosθ/2)

欧拉角转四元数

已知欧拉旋转度为(Y, X, Z)则旋转顺序为y、x、z(unity中本地坐标的顺序)求四元数

x = sin(X / 2)sin(Z / 2)cos(Y / 2) + cos(X / 2)cos(Z / 2)sin(Y / 2)
y = sin(X / 2)cos(Z / 2)cos(Y / 2) + cos(X / 2)sin(Z / 2)sin(Y / 2)
z = cos(X / 2)sin(Z / 2)cos(Y / 2) - sin(X / 2)cos(Z / 2)sin(Y / 2)
w = cos(X / 2)cos(Z / 2)cos(Y / 2) - sin(X / 2)sin(Z / 2)sin(Y / 2)
q = (x, y, z, w)

物体面向目标
插值面向物体
		//目标rotation
         Quaternion TargetRotation = Quaternion.LookRotation(player.transform.position - transform.position, Vector3.up);
        transform.rotation = Quaternion.Slerp(transform.rotation, TargetRotation, Time.deltaTime * 1.5f);
实时面向物体
        // transform.LookAt(player.transform, Vector3.up);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千年奇葩

从来没受过打赏,这玩意好吃吗?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值