three.js之用一个四元数代替两个3D向量的旋转。

时间:2022-03-05 05:35:55

翻译自:http://lolengine.net/blog/2013/09/18/beautiful-maths-quaternion-from-vectors

 

用一个四元数代替两个3D向量的旋转。

 

一个旋转最好的表示方法就是使用一个旋转轴和一个旋转角。旋转轴可以通过两个向量的叉乘得出。

three.js之用一个四元数代替两个3D向量的旋转。

旋转角(最小)可以通过两个向量的点积获得。点积获取的刚好是最小的旋转角。如下两种方法:

three.js之用一个四元数代替两个3D向量的旋转。

 

有了角度和旋转轴我们便可以用代码生成四元数

three.js之用一个四元数代替两个3D向量的旋转。

 

接下来让我们看看通过旋转轴和旋转角构造四元数的公式:

three.js之用一个四元数代替两个3D向量的旋转。

看代码:

 

three.js之用一个四元数代替两个3D向量的旋转。

 

减少三角函数的使用:

通过下面三角函数的公式,减少代码中三角函数的使用,简化代码,

three.js之用一个四元数代替两个3D向量的旋转。

直接看代码:

three.js之用一个四元数代替两个3D向量的旋转。

 

减少平方根的使用:

上述代码中用到 3次nomalize, 每个normalize 里面又有一个Math.sqrt;

 计算法向量 (w) 的模,可以使用下面的公式,

three.js之用一个四元数代替两个3D向量的旋转。

 

sin(θ)的值可以使用

three.js之用一个四元数代替两个3D向量的旋转。

那么代码即可简化为:

three.js之用一个四元数代替两个3D向量的旋转。

 

我们可以清楚的发现创建单位法向量(w)时除了一个 half_sin,构造四元数对象(quat) 又乘了half_sin,因此  half_sin是重复而多余的,简化代码如下:

three.js之用一个四元数代替两个3D向量的旋转。

 

在THREE.js  中进行改进

用些引擎normalize 的速度是很快的,如是我们可以进一步该进代码:

three.js之用一个四元数代替两个3D向量的旋转。

 

通过观察代码我们容易发现,构建四元素对象时,用的是half_cos 的平方,故开平方的代码可以省去:

three.js之用一个四元数代替两个3D向量的旋转。

 

我们可以让四元素乘上 norm_u_norm_v 进一步简化代码

three.js之用一个四元数代替两个3D向量的旋转。

 

如果强迫 使用单位向量(three.js 确实是这样做的) 代码还可以简化为

three.js之用一个四元数代替两个3D向量的旋转。

 

注意:两个向量可能不在同一个平面内,还要进行判断

所有代码如下:

three.js之用一个四元数代替两个3D向量的旋转。

 

如有不对,欢迎抛砖