AI底层系列:用C++实现线性代数的公式推导与算法设计-8.线性变化(3)

接着上一节的内容,我们要实现的是:已知几何元素原本的坐标和用户输入的任意旋转角度,求出旋转后的坐标,先从最简单的二维线段开始,考虑下方通用情况:

已知原线段的端点和旋转角度bbb,那么容易得出目标线段的端点为(Lcos(a+b),Lsin(a+b))(Lcos(a+b), Lsin(a+b))(Lcos(a+b),Lsin(a+b)),其中L=x12+y12L = \sqrt{x_1^2+y_1^2}L=x12+y12 ,由此我们尝试求出通用的旋转角变化矩阵,即:

a11a12a21a22\]\[x1y1\]=\[Lcos(a+b)Lsin(a+b)\] \\left\[ \\begin{array}{c} a_{11}\&a_{12}\\\\ a_{21}\&a_{22} \\end{array} \\right\] \\left\[ \\begin{array}{c} x_1\\\\ y_1 \\end{array} \\right\] = \\left\[ \\begin{array}{c} Lcos(a+b)\\\\ Lsin(a+b) \\end{array} \\right\] \[a11a21a12a22\]\[x1y1\]=\[Lcos(a+b)Lsin(a+b)

利用三角函数公式变化后得出:

a11a12a21a22\]\[x1y1\]=\[L(cosacosb−sinasinb)L(sinacosb+cosasinb)\] \\left\[ \\begin{array}{c} a_{11}\&a_{12}\\\\ a_{21}\&a_{22} \\end{array} \\right\] \\left\[ \\begin{array}{c} x_1\\\\ y_1 \\end{array} \\right\] = \\left\[ \\begin{array}{c} L(cosacosb-sinasinb)\\\\ L(sinacosb+cosasinb) \\end{array} \\right\] \[a11a21a12a22\]\[x1y1\]=\[L(cosacosb−sinasinb)L(sinacosb+cosasinb)

得出线性方程组:

{x1a11+y1a12=Lcosacosb−Lsinasinbx1a21+y1a22=Lsinacosb+Lcosasinb \begin{cases} x_1a_{11}+y_1a_{12}=Lcosacosb-Lsinasinb\\ x_1a_{21}+y_1a_{22}=Lsinacosb+Lcosasinb \end{cases} {x1a11+y1a12=Lcosacosb−Lsinasinbx1a21+y1a22=Lsinacosb+Lcosasinb

由于有x1=Lcosa,y1=Lsinax_1 = Lcosa,y_1 = Lsinax1=Lcosa,y1=Lsina,因此上式可以化为:

{(Lcosa)a11+(Lsina)a12=(Lcosa)cosb−(Lsina)sinb(Lsina)a22+(Lcosa)a21=(Lsina)cosb+(Lcosa)sinb \begin{cases} (Lcosa)a_{11}+(Lsina)a_{12}=(Lcosa)cosb-(Lsina)sinb\\ (Lsina)a_{22}+(Lcosa)a_{21}=(Lsina)cosb+(Lcosa)sinb \end{cases} {(Lcosa)a11+(Lsina)a12=(Lcosa)cosb−(Lsina)sinb(Lsina)a22+(Lcosa)a21=(Lsina)cosb+(Lcosa)sinb

利用形式的一致性,我们容易得出:

{a11=cosba12=−sinba21=sinba22=cosb \begin{cases} a_{11} = cosb\\ a_{12} = -sinb\\ a_{21} = sinb\\ a_{22} = cosb \end{cases} ⎩ ⎨ ⎧a11=cosba12=−sinba21=sinba22=cosb

由此得出通用变化矩阵:

cosb−sinbsinbcosb\] \\left\[ \\begin{array}{c} cosb\&-sinb\\\\ sinb\&cosb \\end{array} \\right\] \[cosbsinb−sinbcosb

可以利用特殊角来验证一下,考虑下方旋转变化:

首先是蓝色线段逆时针旋转90度,端点坐标变化是(2,0)−−>(0,2)(2, 0)-->(0, 2)(2,0)−−>(0,2),带入旋转角,得出旋转矩阵并投入原线段端点:

0−110\]\[20\]=\[02\] \\left\[ \\begin{array}{c} 0\&-1\\\\ 1\&0 \\end{array} \\right\] \\left\[ \\begin{array}{c} 2\\\\ 0 \\end{array} \\right\] = \\left\[ \\begin{array}{c} 0\\\\ 2 \\end{array} \\right\] \[01−10\]\[20\]=\[02

结果正确,然后是将蓝色线段逆时针旋转135度,端点变化为:(2,2)−−>(−22,0)(2, 2)-->(-2\sqrt{2}, 0)(2,2)−−>(−22 ,0),带入旋转角度135度,先得出cos135=−22,sin135=22cos135 = -\frac{\sqrt{2}}{2},sin135 = \frac{\sqrt{2}}{2}cos135=−22 ,sin135=22 ,此处要补充一个知识"逆时针旋转为正角,顺时针旋转为负角",那么带入后得出:

−22−2222−22\]\[22\]=\[−220\] \\left\[ \\begin{array}{c} -\\frac{\\sqrt{2}}{2}\&-\\frac{\\sqrt{2}}{2}\\\\ \\frac{\\sqrt{2}}{2}\& -\\frac{\\sqrt{2}}{2} \\end{array} \\right\] \\left\[ \\begin{array}{c} 2\\\\ 2 \\end{array} \\right\] = \\left\[ \\begin{array}{c} -2\\sqrt{2}\\\\ 0 \\end{array} \\right\] \[−22 22 −22 −22 \]\[22\]=\[−22 0

结果正确,最后是将蓝色线段逆时针旋转180度,端点变化为(3,0)−−>(−3,0)(3, 0)-->(-3, 0)(3,0)−−>(−3,0),带入旋转角,得出cos180=−1,sin180=0cos180 = -1,sin180 = 0cos180=−1,sin180=0,由此得出旋转变化:

−100−1\]\[30\]=\[0−3\] \\left\[ \\begin{array}{c} -1\&0\\\\ 0\&-1 \\end{array} \\right\] \\left\[ \\begin{array}{c} 3\\\\ 0 \\end{array} \\right\] = \\left\[ \\begin{array}{c} 0\\\\ -3 \\end{array} \\right\] \[−100−1\]\[30\]=\[0−3

结果正确,利用从线段处得出的结论,我们尝试对二维的复杂几何图形进行旋转,考虑下方情况:

该图形是人型建模时最常用的胶囊,容易发现其由中部的矩形和两侧的半圆构成,在位变变化中的有效特征就只有三个,不过要说明的是,为了便于渲染和进行复杂的几何变化,在Unity中会将其拆分成多个三角形进行存储,也就是这样:

在实际渲染时会有相应的平滑处理算法,但是底层的几何形体就是这样的了,在此处我们先考虑位变变化,不进行三角形的拆分,先将旋转点平移到原点,然后再进行旋转变化,容易得出系列变化为:

0−110\](\[blue\]+\[−3−3\])+\[33\]=\[red\] \\left\[ \\begin{array}{c} 0\&-1\\\\ 1\&0 \\end{array} \\right\] ( \\left\[ \\begin{array}{c} blue \\end{array} \\right\] + \\left\[ \\begin{array}{c} -3\\\\ -3 \\end{array} \\right\] ) + \\left\[ \\begin{array}{c} 3\\\\ 3 \\end{array} \\right\] = \\left\[ \\begin{array}{c} red \\end{array} \\right\] \[01−10\](\[blue\]+\[−3−3\])+\[33\]=\[red

我们将所有特征点投入(从顶部开始逆时针依次投入),得出:

(3,5)−−>(1,3),(2,4)−−>(2,2),(2,2)−−>(4,2),(3,1)−−>(5,3),(4,2)−−>(4,4),(4,4)−−>(2,4)(3, 5)-->(1, 3),(2, 4)-->(2, 2),(2, 2)-->(4, 2),(3, 1)-->(5, 3),(4, 2)-->(4, 4),(4, 4)-->(2, 4)(3,5)−−>(1,3),(2,4)−−>(2,2),(2,2)−−>(4,2),(3,1)−−>(5,3),(4,2)−−>(4,4),(4,4)−−>(2,4)

结果正确,Unity在底层的具体算法是什么样子的笔者并不确定,但是笔者可以确定使用线性代数一定是一个高效的算法,完整的确定下来旋转后的位置实际上只需要投入三个点,在此处为了演示出正确性笔者才将所有特征点都投入了,可以发现线性代数同样可以处理曲边图形。下面我们将维度扩充到三维,希望求出三维中的通用旋转角度矩阵。在实际应用中,三维的物体的主旋转就只有三种,即绕xxx轴旋转,绕yyy轴旋转和绕zzz轴旋转,通过这三种旋转再配合上平移,就可以实现三维中的任意位变变化,因此在此处我们只讨论这三种旋转,先来看看绕zzz轴的旋转,考虑下方通用变化:

在上图中蓝色线段绕zzz轴旋转了bbb度变为红色线段,坐标变化为(x1,y1,0)−−>(x2,y2,0)(x_1, y_1, 0)-->(x_2, y_2, 0)(x1,y1,0)−−>(x2,y2,0),同样的我们容易求出蓝色线段长度为: L=x12+y12L = \sqrt{x_1^2+y_1^2}L=x12+y12 ,蓝色线段与xxx轴夹角aaa的cos,sincos,sincos,sin,那么我们就可以得出红色线段的坐标为:

x2=Lcos(a+b),y2=Lsin(a+b)x_2 = Lcos(a+b),y_2 = Lsin(a+b)x2=Lcos(a+b),y2=Lsin(a+b)

由此得出变化矩阵方程:

a11a12a13a21a22a23a31a32a33x1y10=Lcos(a+b)Lsin(a+b)0 \left \\begin{array}{c} a_{11}\&a_{12}\&a_{13}\\\\ a_{21}\&a_{22}\&a_{23}\\\\ a_{31}\&a_{32}\&a_{33} \\end{array} \\right \left \\begin{array}{c} x_1\\\\ y_1\\\\ 0 \\end{array} \\right = \left \\begin{array}{c} Lcos(a+b)\\\\ Lsin(a+b)\\\\ 0 \\end{array} \\right a11a21a31a12a22a32a13a23a33 x1y10 = Lcos(a+b)Lsin(a+b)0

同样的我们利用三角函数公式进行变化,得出:

a11a12a13a21a22a23a31a32a33x1y10=Lcosacosb−LsinasinbLsinacosb+Lcosasinb0 \left \\begin{array}{c} a_{11}\&a_{12}\&a_{13}\\\\ a_{21}\&a_{22}\&a_{23}\\\\ a_{31}\&a_{32}\&a_{33} \\end{array} \\right \left \\begin{array}{c} x_1\\\\ y_1\\\\ 0 \\end{array} \\right = \left \\begin{array}{c} Lcosacosb-Lsinasinb\\\\ Lsinacosb+Lcosasinb\\\\ 0 \\end{array} \\right a11a21a31a12a22a32a13a23a33 x1y10 = Lcosacosb−LsinasinbLsinacosb+Lcosasinb0

得出线性方程组:

{x1a11+y1a12+0a13=Lcosacosb−Lsinasinbx1a21+y1a22+0a23=Lsinacosb+Lcosasinbx1a31+y1a32+0a33=0 \begin{cases} x_1a_{11}+y_1a_{12}+0a_{13} = Lcosacosb-Lsinasinb\\ x_1a_{21}+y_1a_{22}+0a_{23} = Lsinacosb+Lcosasinb\\ x_1a_{31}+y_1a_{32}+0a_{33} = 0 \end{cases} ⎩ ⎨ ⎧x1a11+y1a12+0a13=Lcosacosb−Lsinasinbx1a21+y1a22+0a23=Lsinacosb+Lcosasinbx1a31+y1a32+0a33=0

同样的,我们可以进行变化:x1=Lcosa,y1=Lsinax_1 = Lcosa,y_1 = Lsinax1=Lcosa,y1=Lsina,回代到上式,得出:

{(Lcosa)a11+(Lsina)a12+0a13=(Lcosa)cosb−(Lsina)sinb(Lcosa)a21+(Lsina)a22+0a23=(Lcosa)sinb+(Lsina)cosb(Lcosa)a31+(Lsina)a32+0a33=0 \begin{cases} (Lcosa)a_{11}+(Lsina)a_{12}+0a_{13} = (Lcosa)cosb-(Lsina)sinb\\ (Lcosa)a_{21}+(Lsina)a_{22}+0a_{23} = (Lcosa)sinb+(Lsina)cosb\\ (Lcosa)a_{31}+(Lsina)a_{32}+0a_{33} = 0 \end{cases} ⎩ ⎨ ⎧(Lcosa)a11+(Lsina)a12+0a13=(Lcosa)cosb−(Lsina)sinb(Lcosa)a21+(Lsina)a22+0a23=(Lcosa)sinb+(Lsina)cosb(Lcosa)a31+(Lsina)a32+0a33=0

容易发现由于只在xyxyxy平面上进行旋转,全程与zzz坐标无关,因此我们可以令a31,a32,a33a_{31},a_{32},a_{33}a31,a32,a33为零,最终得出变化矩阵:

cosb−sinb0sinbcosb0000 \left \\begin{array}{c} cosb\&-sinb\&0\\\\ sinb\&cosb\&0\\\\ 0\&0\&0 \\end{array} \\right cosbsinb0−sinbcosb0000

我们先把所有变化矩阵都求出来,最后使用复合旋转变化进行验证,下面看到绕xxx轴旋转的情况,考虑下方通用变化:

此时坐标的变化为(0,y1,z1)−−>(0,y2,z2)(0, y_1, z_1)-->(0, y_2, z_2)(0,y1,z1)−−>(0,y2,z2),同理可得线段长度:L=y12+z12,cosa,sinaL = \sqrt{y_1^2+z_1^2},cosa, sinaL=y12+z12 ,cosa,sina,得出变化方程:

a11a12a13a21a22a23a31a32a330y1z1=0y2z2 \left \\begin{array}{c} a_{11}\&a_{12}\&a_{13}\\\\ a_{21}\&a_{22}\&a_{23}\\\\ a_{31}\&a_{32}\&a_{33} \\end{array} \\right \left \\begin{array}{c} 0\\\\ y_1\\\\ z_1 \\end{array} \\right = \left \\begin{array}{c} 0\\\\ y_2\\\\ z_2 \\end{array} \\right a11a21a31a12a22a32a13a23a33 0y1z1 = 0y2z2

由于z2=Lcos(a+b),y2=Lsin(a+b)z_2 = Lcos(a+b),y_2 = Lsin(a+b)z2=Lcos(a+b),y2=Lsin(a+b),再利用三角函数的变化,可以将方程化为:

a11a12a13a21a22a23a31a32a330y1z1=0Lsinacosb+LcosasinbLcosacosb−Lsinasinb \left \\begin{array}{c} a_{11}\&a_{12}\&a_{13}\\\\ a_{21}\&a_{22}\&a_{23}\\\\ a_{31}\&a_{32}\&a_{33} \\end{array} \\right \left \\begin{array}{c} 0\\\\ y_1\\\\ z_1 \\end{array} \\right = \left \\begin{array}{c} 0\\\\ Lsinacosb+Lcosasinb\\\\ Lcosacosb-Lsinasinb \\end{array} \\right a11a21a31a12a22a32a13a23a33 0y1z1 = 0Lsinacosb+LcosasinbLcosacosb−Lsinasinb

得出线性方程组:

{0a11+y1a12+z1a13=00a21+y1a22+z1a23=Lsinacosb+Lcosasinb0a31+y1a32+z1a33=Lcosacosb−Lsinasinb \begin{cases} 0a_{11}+y_1a_{12}+z_1a_{13} = 0\\ 0a_{21}+y_1a_{22}+z_1a_{23} = Lsinacosb+Lcosasinb\\ 0a_{31}+y_1a_{32}+z_1a_{33} = Lcosacosb-Lsinasinb \end{cases} ⎩ ⎨ ⎧0a11+y1a12+z1a13=00a21+y1a22+z1a23=Lsinacosb+Lcosasinb0a31+y1a32+z1a33=Lcosacosb−Lsinasinb

由于z1=Lcosa,y1=Lsinaz_1 = Lcosa,y_1 = Lsinaz1=Lcosa,y1=Lsina,因此上式可以化为:

{0a11+(Lsina)a12+(Lcosa)a13=00a21+(Lsina)a22+(Lcosa)a23=(Lsina)cosb+(Lcosa)sinb0a31+(Lsina)a32+(Lcosa)a33=−(Lsina)sinb+(Lcosa)cosb \begin{cases} 0a_{11}+(Lsina)a_{12}+(Lcosa)a_{13} = 0\\ 0a_{21}+(Lsina)a_{22}+(Lcosa)a_{23} = (Lsina)cosb+(Lcosa)sinb\\ 0a_{31}+(Lsina)a_{32}+(Lcosa)a_{33} = -(Lsina)sinb+(Lcosa)cosb \end{cases} ⎩ ⎨ ⎧0a11+(Lsina)a12+(Lcosa)a13=00a21+(Lsina)a22+(Lcosa)a23=(Lsina)cosb+(Lcosa)sinb0a31+(Lsina)a32+(Lcosa)a33=−(Lsina)sinb+(Lcosa)cosb

得出变化矩阵:

0000cosbsinb0−sinbcosb \left \\begin{array}{c} 0\&0\&0\\\\ 0\&cosb\&sinb\\\\ 0\&-sinb\&cosb \\end{array} \\right 0000cosb−sinb0sinbcosb

最后看到绕yyy轴旋转的情况:

此时坐标变化为(x1,0,z1)−−>(x2,0,z2)(x_1, 0, z_1)-->(x_2, 0, z_2)(x1,0,z1)−−>(x2,0,z2),我们可以求得:L=x12+z12,cosa,sinaL=\sqrt{x_1^2+z_1^2},cosa,sinaL=x12+z12 ,cosa,sina,得出变化方程:

a11a12a13a21a22a23a31a32a33x10z1=x20z2 \left \\begin{array}{c} a_{11}\&a_{12}\&a_{13}\\\\ a_{21}\&a_{22}\&a_{23}\\\\ a_{31}\&a_{32}\&a_{33} \\end{array} \\right \left \\begin{array}{c} x_1\\\\ 0\\\\ z_1 \\end{array} \\right = \left \\begin{array}{c} x_2\\\\ 0\\\\ z_2 \\end{array} \\right a11a21a31a12a22a32a13a23a33 x10z1 = x20z2

同理,利用三角函数变化,可以得出x2=Lcos(a+b),z2=Lsin(a+b)x_2 = Lcos(a+b),z_2 = Lsin(a+b)x2=Lcos(a+b),z2=Lsin(a+b),再利用三角函数变化,得出:

a11a12a13a21a22a23a31a32a33x10z1=Lcosacosb−Lsinasinb0Lsinacosb+Lcosasinb \left \\begin{array}{c} a_{11}\&a_{12}\&a_{13}\\\\ a_{21}\&a_{22}\&a_{23}\\\\ a_{31}\&a_{32}\&a_{33} \\end{array} \\right \left \\begin{array}{c} x_1\\\\ 0\\\\ z_1 \\end{array} \\right = \left \\begin{array}{c} Lcosacosb-Lsinasinb\\\\ 0\\\\ Lsinacosb+Lcosasinb \\end{array} \\right a11a21a31a12a22a32a13a23a33 x10z1 = Lcosacosb−Lsinasinb0Lsinacosb+Lcosasinb

得出线性方程组:

{x1a11+0a12+z1a13=Lcosacosb−Lsinasinbx1a21+0a22+z1a23=0x1a31+0a32+z1a33=Lsinacosb+Lcosasinb \begin{cases} x_1a_{11}+0a_{12}+z_1a_{13} = Lcosacosb-Lsinasinb\\ x_1a_{21}+0a_{22}+z_1a_{23} = 0\\ x_1a_{31}+0a_{32}+z_1a_{33} = Lsinacosb+Lcosasinb \end{cases} ⎩ ⎨ ⎧x1a11+0a12+z1a13=Lcosacosb−Lsinasinbx1a21+0a22+z1a23=0x1a31+0a32+z1a33=Lsinacosb+Lcosasinb

由于x1=Lcosa,z1=Lsinax_1 = Lcosa,z_1 = Lsinax1=Lcosa,z1=Lsina,带入上式,得出:

{(Lcosa)a11+0a12+(Lsina)a13=(Lcosa)cosb−(Lsina)sinb(Lcosa)a21+0a22+(Lsina)a23=0(Lcosa)a31+0a32+(Lsina)a33=(Lcosa)sinb+(Lsina)cosb \begin{cases} (Lcosa)a_{11}+0a_{12}+(Lsina)a_{13} = (Lcosa)cosb-(Lsina)sinb\\ (Lcosa)a_{21}+0a_{22}+(Lsina)a_{23} = 0\\ (Lcosa)a_{31}+0a_{32}+(Lsina)a_{33} = (Lcosa)sinb+(Lsina)cosb \end{cases} ⎩ ⎨ ⎧(Lcosa)a11+0a12+(Lsina)a13=(Lcosa)cosb−(Lsina)sinb(Lcosa)a21+0a22+(Lsina)a23=0(Lcosa)a31+0a32+(Lsina)a33=(Lcosa)sinb+(Lsina)cosb

得出变化矩阵为:

cosb0−sinb000sinb0cosb \left \\begin{array}{c} cosb\&0\&-sinb\\\\ 0\&0\&0\\\\ sinb\&0\&cosb \\end{array} \\right cosb0sinb000−sinb0cosb

至此我们求出了三维中全部的变化矩阵,总结一下就是:

绕xxx轴旋转:

0000cosbsinb0−sinbcosb \left \\begin{array}{c} 0\&0\&0\\\\ 0\&cosb\&sinb\\\\ 0\&-sinb\&cosb \\end{array} \\right 0000cosb−sinb0sinbcosb

绕yyy轴旋转:

cosb0−sinb000sinb0cosb \left \\begin{array}{c} cosb\&0\&-sinb\\\\ 0\&0\&0\\\\ sinb\&0\&cosb \\end{array} \\right cosb0sinb000−sinb0cosb

绕zzz轴旋转:

cosb−sinb0sinbcosb0000 \left \\begin{array}{c} cosb\&-sinb\&0\\\\ sinb\&cosb\&0\\\\ 0\&0\&0 \\end{array} \\right cosbsinb0−sinbcosb0000

下面来进行验证,考虑如下旋转:

先将xxx轴上的蓝色线段旋转到yyy轴变为红色线段,再将yyy轴上的线段旋转到zzz轴变为绿色线段,端点变化流程为:(3,0,0)−−>(0,3,0)−−>(0,0,3)(3, 0, 0)-->(0, 3, 0)-->(0, 0, 3)(3,0,0)−−>(0,3,0)−−>(0,0,3),利用旋转矩阵进行变化,带入旋转角,此时转向成了问题,基于xyxyxy平面上的转向规定,我们推测需要让正轴一直位于右侧,也就是说绕zzz轴旋转时我们这样看:

绕xxx轴旋转时我们这样看:

绕yyy轴旋转时我们这样看:

这样正轴就会一直位于我们的右侧,满足在二维平面中对于旋转角的规定,那么就可以得知最初绕zzz轴旋转时是旋转了90度(逆时针),然后绕xxx轴旋转时是旋转了-90度(顺时针),因此得出绕zzz轴旋转的旋转矩阵为:

0−10100000 \left \\begin{array}{c} 0\&-1\&0\\\\ 1\&0\&0\\\\ 0\&0\&0 \\end{array} \\right 010−100000

绕xxx轴旋转的矩阵为:

00000−1010 \left \\begin{array}{c} 0\&0\&0\\\\ 0\&0\&-1\\\\ 0\&1\&0 \\end{array} \\right 0000010−10

得出系列变化:

00000−10100−10100000300=00000−1010030=003 \left \\begin{array}{c} 0\&0\&0\\\\ 0\&0\&-1\\\\ 0\&1\&0 \\end{array} \\right \left \\begin{array}{c} 0\&-1\&0\\\\ 1\&0\&0\\\\ 0\&0\&0 \\end{array} \\right \left \\begin{array}{c} 3\\\\ 0\\\\ 0 \\end{array} \\right = \left \\begin{array}{c} 0\&0\&0\\\\ 0\&0\&-1\\\\ 0\&1\&0 \\end{array} \\right \left \\begin{array}{c} 0\\\\ 3\\\\ 0 \\end{array} \\right = \left \\begin{array}{c} 0\\\\ 0\\\\ 3 \\end{array} \\right 0000010−10 010−100000 300 = 0000010−10 030 = 003

结果正确,将二维思维迁移到三维就是所谓的维度扩充,该思路是笔者常用的思考方法,原因很简单,作为三维生物,我们在处理低维度信息时是比较轻松且容易理解的,然后又由于维度之间拥有极强的规律性和关联性,这就为维度扩充提供了可能性,当然笔者的方法不一定适合你,在此处仅提供一种思路。下面让我们来验证二维旋转和三维旋转的另一种情况,在Unity游戏引擎中,坐标轴分为两种,一是绝对固定的世界坐标轴,也就是笔者上图的那种坐标轴,到目前为止我们所有的探讨都是在绝对固定坐标轴中进行的,因为这比较简单,坐标轴固定是比较好理解的,然而在实际应用中还存在另一种坐标轴,也就是相对坐标轴,这种坐标轴会随着物体的运动而变化,比如:

上图中最大个的那个坐标轴就是绝对坐标轴,在Unity中也称为世界坐标轴,是绝对固定不动的,而绕圆旋转的红点上的坐标轴就是相对坐标轴,以红色圆心为原点,坐标轴随红点的运动而不断变化,明显可以感觉到相对坐标轴比较复杂,因为其是动态变化的,但是在数学,几何,物理,AI,机械,游戏引擎...等大量实际应用中,相对坐标轴都是一个非常强大的表达工具,也就是说我们必须要啃下这块硬骨头了,先从二维平面开始探索,为了表述方便,我们同时使用绝对坐标轴和相对坐标轴并且两种坐标轴的单位距离和方向相同,让一个物体拥有绝对坐标和相对坐标,也就是这样的:

此时在红色正方形的几何中心存在一个相对坐标轴,其右上方端点的绝对坐标是(5,3)(5, 3)(5,3),相对坐标是(1,1)(1, 1)(1,1),在平移时显然是使用绝对坐标会更加方便,又或者说在相对坐标轴中的几何元素是无法相对于自己的坐标轴平移的,因为坐标轴会随着几何元素的移动而移动,但是在旋转时使用相对坐标轴就比较方便了,让我们来看看Unity中的二维几何元素是如何使用相对坐标轴来进行旋转的:

容易看出这就是绕相对坐标轴的原点进行旋转,并且坐标轴本身也会发生旋转,此时我们可以假想是相对坐标轴的旋转带动了外部几何元素的旋转,那么我们就可以抽象掉外部的几何元素,直接对相对坐标轴进行旋转,也就是这样:

当几何元素变得非常复杂时,这种以相对坐标轴带动几何元素旋转的方法就非常优雅了,下面来尝试一下,笔者想出的思路是:我们先让相对坐标轴相对于绝对坐标轴进行旋转,求出变化矩阵后再作用于几何元素,这就有点像是把各种复杂的几何元素的特征全部统一成了相对坐标轴,目前还无法确定是否正确,让我们来测试一下,考虑下方复杂二维图形的位变变化:

将蓝色的椭圆位移并旋转成红色椭圆,曲边图形本身是非线性的,想要找出准确的特征会比较困难,但是使用相对坐标轴就非常方便了,容易发现我们需要先将坐标轴的原点进行平移,然后再进行旋转,将固定坐标轴的原点作为旋转点,变化流程就是这样的:

容易得出系列变化为:

0−110\](\[blue\]+\[−4−2\])+\[−23\]=\[red\] \\left\[ \\begin{array}{c} 0\&-1\\\\ 1\&0 \\end{array} \\right\] ( \\left\[ \\begin{array}{c} blue \\end{array} \\right\] + \\left\[ \\begin{array}{c} -4\\\\ -2\\\\ \\end{array} \\right\] ) + \\left\[ \\begin{array}{c} -2\\\\ 3\\\\ \\end{array} \\right\] = \\left\[ \\begin{array}{c} red \\end{array} \\right\] \[01−10\](\[blue\]+\[−4−2\])+\[−23\]=\[red

将椭圆的端点投入,得出:

(2,2)−−>(−2,1),(4,1)−−>(−1,3),(6,2)−−>(−2,5),(4,3)−−>(−3,3)(2, 2)-->(-2, 1),(4, 1)-->(-1, 3),(6, 2)-->(-2, 5),(4, 3)-->(-3, 3)(2,2)−−>(−2,1),(4,1)−−>(−1,3),(6,2)−−>(−2,5),(4,3)−−>(−3,3)

结果正确,这种方法显然比找特征要更加简便,关键是该方法是否具备通用性,考虑下方不规则图形的位变变化:

容易得出系列变化为:

0−110\](\[blue\]+\[−5−3\])+\[−33\]=\[red\] \\left\[ \\begin{array}{c} 0\&-1\\\\ 1\&0 \\end{array} \\right\] ( \\left\[ \\begin{array}{c} blue \\end{array} \\right\] + \\left\[ \\begin{array}{c} -5\\\\ -3\\\\ \\end{array} \\right\] ) + \\left\[ \\begin{array}{c} -3\\\\ 3\\\\ \\end{array} \\right\] = \\left\[ \\begin{array}{c} red \\end{array} \\right\] \[01−10\](\[blue\]+\[−5−3\])+\[−33\]=\[red

投入验证点,得出:

1:(3,2)−−>(−2,1)(3, 2)-->(-2, 1)(3,2)−−>(−2,1),2:(5,1)−−>(−1,3)(5, 1)-->(-1, 3)(5,1)−−>(−1,3),3:(7,3)−−>(−3,5)(7, 3)-->(-3, 5)(7,3)−−>(−3,5),4:(6,5)−−>(−5,4)(6, 5)-->(-5, 4)(6,5)−−>(−5,4),5:(3,5)−−>(−5,1)(3, 5)-->(-5, 1)(3,5)−−>(−5,1)

结果正确,我们推测该方法是具备通用性的,为了进行严谨的证明,必须先深入理解线性与线性变化,首先在最初有关线性最直观的理解就是直线,也就是非曲,这一点从线性方程的未知数只能出现一次项就容易得出,随着学习的深入,笔者在前方章节提出了线性的实质是增量相同,斜率一致 ,这本质上就是抽象出了直线的代数性质,在后续的验证中我们发现:1.平行的线段在经过了同一个线性变换后依旧保持平行;2.非平行的线段在经过了同一个线性变换后依旧保持非平行 ,这两点也是我们使用三角形作为几何单位的原因,由此我们推测,线性本质上就是对非曲的描述,可以是直线,也可以是线段,总之不能出现拐点,必须满足增量相同,斜率一致,那么线性变换在几何本质上就是对非曲图形的变化,主要就是变化线段,所谓的线性变化不改变线性就是:对一条线段使用线性变换,得出的必然还是一条线段,不会让线段出现拐点 ,那么线性变换能够变化的元素就非常明确了,即:1.起点(线段起点位置),2.增量(线段斜率),3.范围(线段长度) 。从这个角度看,1.平行的线段在经过了同一个线性变换后依旧保持平行;2.非平行的线段在经过了同一个线性变换后依旧保持非平行 就是线性变换不改变线段增量的一致性与非一致性 ,容易发现,线性代数研究的核心对象就是线段与线段的变化,而在几何上,任意几何元素都可以使用无数线段进行表示,任意几何变化都可以变为线段的变化,虽然我们说点才是几何图形的基本单位,但是如果以点为单位的话,那么就无法直观的表示出旋转,而且在几何直观上点太小了,这就有点像是在计算机中最小的单位是bit,但是我们一般都会使用字节作为基本单位,在任何学科中都是如此,分的太细就难以把握宏观,分的太粗就难以研究细节,而线段显然就是几何中一个完美的平衡点,这也就是线性代数以线段为核心研究对象的原因,在底层上就决定了线性代数必然可以描述任意几何图形与几何变化且拥有化繁为简的能力。看回到上方的几何图形变化,我们任意取其中一点,并将其连接相对坐标轴的原点,得出一条线段:

我们将该线段投入系列变化:

0−110\](\[blue\]+\[−5−3\])+\[−33\]=\[red\] \\left\[ \\begin{array}{c} 0\&-1\\\\ 1\&0 \\end{array} \\right\] ( \\left\[ \\begin{array}{c} blue \\end{array} \\right\] + \\left\[ \\begin{array}{c} -5\\\\ -3\\\\ \\end{array} \\right\] ) + \\left\[ \\begin{array}{c} -3\\\\ 3\\\\ \\end{array} \\right\] = \\left\[ \\begin{array}{c} red \\end{array} \\right\] \[01−10\](\[blue\]+\[−5−3\])+\[−33\]=\[red

我们已经证明,向量平移变化和矩阵的旋转变化是具备通用性的,也就是说矩阵:

0−110\] \\left\[ \\begin{array}{c} 0\&-1\\\\ 1\&0 \\end{array} \\right\] \[01−10

作用于任何以原点为起点的线段的效果都是逆时针旋转90度,由此我们可以得出连接几何图形上的任意一点与相对坐标轴原点都可以得出一条线段,将该线段投入系列变化后都会是"平移+旋转90度",从直观上来看就是这样的:

得出的就是目标点位置,最终我们可以证明:在二维位变变化时,变化任意几何元素等价于变化该几何元素的相对坐标轴 ,利用该方法,我们几乎可以实现口算任意复杂的二维几何元素的任意位变变化,再配合上伪向量与伪矩阵,就可以实现在一个位置求出了几何元素,在任意位置都可以复用该几何元素,容易推知,在三维中该方法同样适用,由此我们得出了相对坐标系的第一个用法就是作为任意几何元素的固定特征并以此进行简便的位变变化。

  有关线性变换的部分就结束了,在后续章节我们将正式进入矩阵运算的部分。

相关推荐
人工智能培训1 小时前
世界模型内嵌,感知交互跃迁
大数据·数据库·人工智能·神经网络·生成对抗网络
Yunzenn1 小时前
强化学习1-Liu2026_GFlowRL_精读笔记
人工智能·笔记·深度学习·机器学习·transformer·集成学习·vllm
fuquxiaoguang1 小时前
当算力成为一种“出口”:Meta联手信实重塑南亚AI云格局
人工智能·meta·算力租赁·数据主权·印度
金融Tech趋势派1 小时前
金融行业如何用企业微信大圆提升客户服务效率?
人工智能·企业微信
甄同学1 小时前
第二十篇:MCP协议集成,Claude Code如何扩展AI Agent的能力边界
开发语言·人工智能·qt
阿萨德528号1 小时前
Kimi K3:全球首个开源 3T 级大模型,技术解读与手记
人工智能·ai·语言模型·开源
天天爱吃肉82181 小时前
# 商用车多体动力学整车仿真学习笔记(开篇总览)
人工智能·笔记·python·功能测试·学习·汽车
田里的水稻1 小时前
EP_局域网传输音视频的主流方案
运维·人工智能·机器人·音视频
武子康1 小时前
GitHub Copilot for JetBrains 架构拆解:Provider / Endpoint / Skills / Sandbox / Polic
人工智能·ai编程·github copilot