700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 绕坐标轴以及任意轴的旋转矩阵的推导

绕坐标轴以及任意轴的旋转矩阵的推导

时间:2020-01-27 05:41:28

相关推荐

绕坐标轴以及任意轴的旋转矩阵的推导

概述

本文主要是针对《3D数学基础-图形与游戏开发》这本书的读书笔记,这本书前面部分还是讲得挺好的,有时间还是建议读一下。

旋转矩阵的推导

旋转矩阵怎么来的我倒一直都没有概念,这本书里面对旋转矩阵的来历倒是给了我一些启发。

首先从二维的旋转矩阵开始

[cosθsinθ−sinθcosθ]\begin{bmatrix} cos\theta & sin\theta \\ -sin\theta & cos\theta \\ \end{bmatrix} [cosθ−sinθ​sinθcosθ​]

推导的方式就是直接找点代入:

想象点(1,0),绕原点逆时针旋转θ\thetaθ,我们把(1,0)和旋转矩阵相乘,得到的就是旋转矩阵第一行的信息,那显然,第一行就是cosθ,sinθcos\theta,sin\thetacosθ,sinθ,同理,代入(0,1)到旋转矩阵也能得到旋转矩阵第二行的值。

不得不承认,这个pdf里面截的图要把人看瞎了,但是问题不大,大概是什么意思还是能明白的。

对于三维旋转绕坐标轴旋转的矩阵来说,推导也是同理的,代入相关的点的坐标即可,图书里面有,但是pdf特别糊,就不截了。也可以理解为三维坐标系投影到二维中,然后运用二维的旋转矩阵公式。

下面就是绕x轴的旋转矩阵,可以理解为在YOZ平面进行旋转,这样的话直接代入上面的二维的公式也行。

[1000cosθsinθ0−sinθcosθ]\begin{bmatrix} 1& 0&0\\0&cos\theta & sin\theta \\0& -sin\theta & cos\theta \\ \end{bmatrix} ⎣⎡​100​0cosθ−sinθ​0sinθcosθ​⎦⎤​

对于绕y轴和z轴的矩阵的由来就不再赘述了。

绕任意轴的旋转矩阵

这个推导看起来还是很复杂的,为了后面四元数部分的理解,这个推导还是有必要看一下的!

我们假设旋转轴通过原点,用单位向量n来描述这个旋转轴,用θ\thetaθ来描述旋转的角度。我们只需要用n和θ\thetaθ就可以推导出来最后的旋转矩阵。

实际的推导我们只需要通过书里面一张图就很容易去理解了

电子版的图太糊了,我画图简单的山寨了一份。

交代一下背景,v绕着n旋转θ\thetaθ

v∥是v在n上的投影,v∥=(v* n)n,v* n等于投影长度,乘上方向的单位矩阵n,也就得到了最后的v∥

v⊥是垂直于v∥的分量,有v⊥=v-v∥ = v-(v* n)n

w是垂直于v∥和v⊥的分量,长度等于v⊥,w=n x v⊥

然后书上就来了v⊥’=v⊥cosθ+wsinθ,这个一开始我还是不是很理解的,后来我把旋转的那个投影到平面上,也就是如下图所示,因为是旋转,所以v⊥’的长度一定是等于v⊥的,当然也等于w,所以如下图所示,投影到两个坐标轴上面,于是就有了上面的公式。

在知道了v⊥’的情况下,最后的v’值就是v∥+v⊥’

代入所有的值,就有v’ = (v-(v* n)n)cosθ+(nxv)sinθ+(v* n)n

那么我们知道了坐标变换,该如何去得到变换矩阵呢,这又回到了我们前面提到的思路,分别代入[1,0,0],[0,1,0],[0,0,1]点到变换公式中,得到的三个向量分别作为矩阵的三行就行了,最后的旋转矩阵如下所示:

[nx2(1−cosθ)+cosθnxny(1−cosθ)+nzsinθnxnz(1−cosθ)−nysinθnxny(1−cosθ)−nzsinθny2(1−cosθ)+cosθnynz(1−cosθ)+nxsinθnxnz(1−cosθ)+nysinθnynz(1−0cosθ)−nxsinθnx2(1−cosθ)+cosθ]\begin{bmatrix} n_x^2(1-cos\theta)+cos\theta & n_xn_y(1-cos\theta)+n_zsin\theta&n_xn_z(1-cos\theta)-n_ysin\theta\\ n_xn_y(1-cos\theta)-n_zsin\theta&n_y^2(1-cos\theta)+cos\theta&n_yn_z(1-cos\theta)+n_xsin_\theta\\ n_xn_z(1-cos\theta)+n_ysin\theta&n_yn_z(1-0cos\theta)-n_xsin\theta&n_x^2(1-cos\theta)+cos\theta \end{bmatrix}⎣⎡​nx2​(1−cosθ)+cosθnx​ny​(1−cosθ)−nz​sinθnx​nz​(1−cosθ)+ny​sinθ​nx​ny​(1−cosθ)+nz​sinθny2​(1−cosθ)+cosθny​nz​(1−0cosθ)−nx​sinθ​nx​nz​(1−cosθ)−ny​sinθny​nz​(1−cosθ)+nx​sinθ​nx2​(1−cosθ)+cosθ​⎦⎤​

markdown输入矩阵挺爽的。。。。

在unity实现

基本思路就是给定一条直线,比如说x=y,然后把基于x=y的旋转矩阵实时传入着色器,让物体随着时间能绕着x=y进行旋转。

脚本很简单,里面包括了我们之前推导的旋转矩阵,不过值的注意的点是,记得把方向归一化,这个问题我找了好长时间才发现。

using System.Collections;using System.Collections.Generic;using UnityEngine;public class RotateMatrixTest : MonoBehaviour{public float speed;public Material mat;public Vector3 n;public float currentTheta;private Matrix4x4 calculateRotateMatrix(Vector3 n,float theta){Matrix4x4 RotationMatrix = new Matrix4x4();RotationMatrix[0, 0] = n.x * n.x * (1 - Mathf.Cos(theta)) + Mathf.Cos(theta);RotationMatrix[0, 1] = n.x * n.y * (1 - Mathf.Cos(theta)) + n.z * Mathf.Sin(theta);RotationMatrix[0, 2] = n.x * n.z * (1 - Mathf.Cos(theta)) - n.y * Mathf.Sin(theta);RotationMatrix[0, 3] = 0;RotationMatrix[1, 0] = n.x * n.y * (1 - Mathf.Cos(theta)) - n.z * Mathf.Sin(theta);RotationMatrix[1, 1] = n.y * n.y * (1 - Mathf.Cos(theta)) + Mathf.Cos(theta);RotationMatrix[1, 2] = n.y * n.z * (1 - Mathf.Cos(theta)) + n.x * Mathf.Sin(theta);RotationMatrix[1, 3] = 0;RotationMatrix[2, 0] = n.x * n.z * (1 - Mathf.Cos(theta)) + n.y * Mathf.Sin(theta);RotationMatrix[2, 1] = n.y * n.z * (1 - Mathf.Cos(theta)) - n.x * Mathf.Sin(theta);RotationMatrix[2, 2] = n.z * n.z * (1 - Mathf.Cos(theta)) + Mathf.Cos(theta);RotationMatrix[2, 3] = 0;RotationMatrix[3, 0] = 0;RotationMatrix[3, 1] = 0;RotationMatrix[3, 2] = 0;RotationMatrix[3, 3] = 1;return RotationMatrix;}private void Update(){Vector3 normalizedN = n.normalized;currentTheta += speed;if (currentTheta > 360 || currentTheta < -360)currentTheta = 0;mat.SetMatrix("_RotationMatrix", calculateRotateMatrix(normalizedN, Mathf.Deg2Rad*currentTheta));}}

着色器代码如下(我们是绕着模型空间来旋转的):

Shader "Unlit/rotateTest"{Properties{_MainTex ("Texture", 2D) = "white" {}}SubShader{Tags { "RenderType"="Opaque" }Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;float4 worldPos : TEXCOORD1;};sampler2D _MainTex;float4 _MainTex_ST;float4x4 _RotationMatrix;v2f vert (appdata v){v2f o;fixed4 rotPos = mul(_RotationMatrix,v.vertex);o.vertex = UnityObjectToClipPos(rotPos);o.uv = TRANSFORM_TEX(v.uv, _MainTex);return o;}fixed4 frag (v2f i) : SV_Target{// sample the texturefixed4 col = tex2D(_MainTex, i.uv);return col;}ENDCG}}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。