下面的内容是阅读3D数学基础后结合自己的理解的总结
Unity中应用
我们接触到的地方就是Unity的Transform组件。Transform组件维护了四元数实现方位角位的变换。但是我们也看到Transform组件提供了eulerAgnles属性,按理说里面也实现了欧拉角的,但事实并不是这样。接下来详细分析下
首先看看类似与这种操作,我们对一个GameObject实现旋转的时候,可以直接对其transform组件的eulerAngles属性赋值需要旋转的角度即可。
1 |
|
这个是transform的eulerAngles的实现,可以看到其实里面直接把欧拉角转换成了四元数来处理,所以欧拉角其实只是作为一个方法的表达形式,并没有作为Transform的成员变量之类的属性来维护 (实际上也不需要,因为有了四元数之后,欧拉角和四元数就可以实现相互的转换)
1 |
|
我们想对一个GameObject实现旋转还可以对其的transform组件的rotation属性以四元素的方式赋值,来实现旋转。
1 |
|
对于rotation属性,其具体实现是这样的
1 |
|
可以看到标红色的那行,传入的四元数被赋值参数被赋值给了m_LocalRotation成员变量。
上面介绍了在Unity里面封装的Quaternion的方位与角位的情况。那么下面Quaternion里面常用到的一个叫做Lerp的方法。相应的这个方法有一个 对应的Slerp方法。那么这两个方法到底有什么区别呢?下面来看看。
线性插值和球面线性插值的原理
Lerp是用来求两个目标之前的差值,其表达式为Lerp(a, b, t)。a和b分别为起始和终点两个点,t为差值参数变量,范围在0到1之间。Lerp表示为标准的线性差值公式的话,其公式为:
1 |
|
代码实现着这样的:
1 |
|
Slerp的计算方式(里面数学公式编辑比较麻烦,干脆直接写下来上图片了):
得出了推导公式,那么代码实现就比较简单了:
1 |
|
两种方式比较: Lerp更少的计算量,Slerp更加平滑。实际测试下使用Slerp和Lerp的运动效果
1 |
|
通过一个个的小球,我把每次Slerp和Lerp的插值画出来,形成了一个轨迹(其中红色是Slerp的插值轨迹,白色的是Lerp的插值轨迹)
通过这个轨迹图片可以看得到(由于各个小球的Z周有一点差异,导致画面有一点透视效果),代码Slerp的红色小球的轨迹相邻的之间距离比较均匀,但是代表Lerp的白色的小球两球之前的距离由最开始逐渐变小然后到达中间之后又开始变大。分析之后可以归结到下面两张图片中(左图描述Lerp,右图描述Slerp)。Lerp求得的是四元数在圆上的弦上的等分,而Slerp求得的是四元数载圆上的圆弧的等分(论据的图是参考的这里)。
项目中的使用问题:
1 |
|