使3D空間中物體朝向和其速度方向一致的旋轉矩陣計算方案
來源:程序員人生 發布時間:2015-06-11 08:15:13 閱讀次數:3379次
在3D空間中的物體以某1速度運動,有時候需要這個物體的朝向和速度的方向1致,
為了實現這個目標我們1般借助旋轉矩陣 M 來將物體旋轉到對應的朝向。
例如速度方向矢量 spdV: Vector3D(1,2,3),
X軸基向量為 axis_x: Vector3D(1,0,0), 這個矢量的方向和3D物體不做任何旋轉時候的默許朝向1致
3D矢量 cross_x 記錄了 axis_x 叉乘 spdV 的結果.
算出矩陣 M 的方法1:
先計算出 spdV 和 axis_x 兩矢量之間的弧度值 rad(可用余弦函數計算), 然后用1個單位矩陣 m0,
讓 m0 繞 軸 cross_x 旋轉 rad, 就能夠得到結果矩陣 M 了
算出矩陣 M 的方法2(此方法計算進程簡潔,因此可以用在有些不能直接使用矩陣的地方例如有些Shader計算):
通過幾何算法直接算出 矩陣M 3個正交軸的基向量(axis_x,axis_y,axis_z)
如何計算呢? 請見下面的代碼:
<span style="white-space:pre"> </span>/**
* 通過速度, 計算物體朝向矩陣的3個軸的數據
* */
public static function calcDirecMatByVelocity(spdv:Vector3D):Vector.<Vector3D> {
// 記錄x軸的基向量
var axis_x:Vector3D = new Vector3D(1, 0, 0);
// axis_x和spdv 叉乘
var cross_x:Vector3D = axis_x.crossProduct(spdv);
// cross_x和spdv 叉乘,并將叉乘結果記錄在 MathCalc.outCrossV 這個3D矢量中,用這個函數是為了不產生新的3d矢量對象
MathCalc.crossV3D2(cross_x, spdv);
cross_x.normalize();
MathCalc.outCrossV.normalize();
//
cross_x.x = 0.5 * (cross_x.x + MathCalc.outCrossV.x);
cross_x.y = 0.5 * (cross_x.y + MathCalc.outCrossV.y);
cross_x.z = 0.5 * (cross_x.z + MathCalc.outCrossV.z);
// 至此, 已計算出了 新的z軸
cross_x.normalize();
// 得到 新的 y軸
var axis_y:Vector3D = cross_x.crossProduct(spdv);
axis_y.normalize();
// spdv 就是 新x 軸, 標準化
axis_x.setTo(spdv.x,spdv.y,spdv.z);
axis_x.normalize();
//
var vs:Vector.<Vector3D> = new Vector.<Vector3D>();
vs.push(axis_x,axis_y,cross_x);
return vs;
}
原理解釋:
首先, 旋轉矩陣 M 的X軸基向量axis_x,在空間上和spdV重合,因此spdV標準化了以后,就是X軸基向量axis_x
而 cross_x 這個旋轉軸 和 spdv 叉乘的結果MathCalc.outCrossV 是落在了 M 表示的空間的 YOZ 平面上,
旋轉軸 cross_x 也落在 M 表示的空間的 YOZ 平面上。
而且 axis_z 在YOZ 平面上恰好就是 MathCalc.outCrossV 和 旋轉軸 cross_x 夾角的中分線,因此可以直接用計算
中點的方式直接算出 axis_z(z軸的基向量)
有了 axis_z, 由于3個基向量相互垂直,因此再通過叉乘計算出 axis_y
至此,得到了旋轉矩陣 M, 例如此算法可以用于 agal計算粒子的速度朝向
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈