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

###### 延长坐标系中的向量
直接乘数值,结果方向不变,长度改变
```c
a=(x,y) * n

旋转

点旋转

求点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}

//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)

弧度

弧度的意义和周长差不多
弧度单位是:rad
角度(∠360°) = 弧度(2πr) = 2π rad
角度(∠180°) = 弧度(2Πr / 2) = π rad
角度(∠90°) = 弧度(2Πr / 4) = π/2 rand
弧度(1rad) = 角度(2pi*r / r)

弧度转周长
1rad = 半径r
弧度转角度
1rad = (180/π)° ≈ 57.3°
角度转弧度
1° = (π/180)rad ≈ 0.01745rad

角度

已知夹角角度求相关两边的比

三角函数:sin、cos、tan、cot、sec、csc

已知两边和夹角,求第三边

aa = bb + cc - 2bc * cosθ

关于欧拉角旋转矩阵等计算知识,知乎上有篇好文:https://zhuanlan.zhihu.com/p/45404840

发布了134 篇原创文章 · 获赞 37 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/lengyoumo/article/details/104002193