使3D空间中物体朝向和其速度方向一致的旋转矩阵计算方案



在3D空间中的物体以某一速度运动,有时候需要这个物体的朝向和速度的方向一致,
为了实现这个目标我们一般借助旋转矩阵 M 来将物体旋转到对应的朝向。


例如速度方向矢量 spdV: Vector3D(1,2,3),
X轴基向量为 axis_x: Vector3D(1,0,0), 这个矢量的方向和3D物体不做任何旋转时候的默认朝向一致
3D矢量 cross_x 记录了 axis_x 叉乘 spdV 的结果.


算出矩阵 M 的方法一:
先计算出 spdV 和 axis_x 两矢量之间的弧度值 rad(可用余弦函数计算), 然后用一个单位矩阵 m0,
让 m0 绕 轴 cross_x 旋转 rad, 就可以得到结果矩阵 M 了


算出矩阵 M 的方法二(此方法计算过程简洁,因此可以用在有些不能直接使用矩阵的地方例如有些Shader计算):
通过几何算法直接算出 矩阵M 三个正交轴的基向量(axis_x,axis_y,axis_z)

如何计算呢? 请见下面的代码:

                 /**
		 * 通过速度, 计算物体朝向矩阵的三个轴的数据
		 * */
		 public static function calcDirecMatByVelocity(spdv:Vector3D):Vector.<Vector3D> {
			var axis_x:Vector3D = spdv.clone();
			axis_x.normalize();
			// 处理速度和x轴基向量朝向重合导致叉乘为零的问题
			if (axis_x.x != 0 && (Math.abs(axis_x.y) < 0.0000001 && Math.abs(axis_x.z) < 0.0000001)) {
				return Vector.<Vector3D>([new Vector3D(1, 0, 0), new Vector3D(0, 1, 0), new Vector3D(0, 0, 1)]);
			}
			
			// 记录x轴的基向量
			axis_x.setTo(1,0,0);// = 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();
			//
			
			// 0.5 * 其实可以不要
			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, 由于三个基向量相互垂直,因此再通过叉乘计算出 axis_y
至此,得到了旋转矩阵 M, 例如此算法可以用于 agal计算粒子的速度朝向

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值