使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)

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

<span style="white-space:pre">		</span>/**
		 * 通过速度, 计算物体朝向矩阵的三个轴的数据
		 * */
		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, 由于三个基向量相互垂直,因此再通过叉乘计算出 axis_y

至此,得到了旋转矩阵 M, 例如此算法可以用于 agal计算粒子的速度朝向

时间: 2024-12-30 04:29:47

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

3D空间中射线与轴向包围盒AABB的交叉检测算法

引言 在上一节中,我讲述了如何实现射线与三角形的交叉检测算法.但是,我们应该知道,在游戏开发中,一个模型有很多的三角形构成,如果要对所有的物体,所有的三角形进行这种检测,就算现在的计算机运算能力,也是无法高效的完成.所以,我们需要通过其他的手段来提早剔除一些不可能发生交叉的物体,这种早退的思想,大量的运用在3D游戏技术中.在本篇文章中,我将像大家讲述如何实现射线与轴向包围盒AABB的交叉检测.如果读者不明白什么是轴向包围盒,请看这篇文章. Ray-AABB交叉检测算法 现如今,有很多的Ray-A

Qt_OpenGL:3D空间中移动图像

Qt_OpenGL:3D空间中移动图像 //.h #ifndef GLWIDGET_H #define GLWIDGET_H #include <QGLWidget> #include <QtOpenGL> class QGLWidget; class QTimer; typedef struct Stars{ public: int r, g, b; GLfloat dist, angle; }Stars; class GLWidget : public QGLWidget {

在3D空间中绘制四边形

在3D空间中绘制四边形 四边形 GL_QUADS OpenGL的GL_QUADS图元用于绘制四边形,它根据每四个顶点绘制一个四边形. 注意,在使用四边形时,必需记住一个重要规则:一个四边形的四个角必须位于同一个平面中(不存在弯曲的四边形).如图所示 四边形带 GL_QUAD_STRIP 该图元指定一个连接的四边形带.它们都保持相同方向的环绕.如图所示 通用多边形 GL_POLYGON 我们可以用它绘制任意数量的多边形.与四边形一样,多边形的所有顶点也必须位于同一平面中.如果想越过这个规则,可以采

3D空间中射线与三角形的交叉检测算法

引言 射线Ray,在3D图形学中有很多重要的应用.比如,pick操作就是使用射线Ray来实现的,还有诸如子弹射线的碰撞检测等等都可以使用射线Ray来完成.所以,在本次博客中,将会简单的像大家介绍下,如何进行Ray-Triangle的交叉检测. Ray-Triangle交叉检测算法 在Tomas Moller的MT97论文中,提出了一种新的算法.这种算法能够减少以前进行Ray-Triangle交叉检测所需要的内存消耗.在以前,进行Ray-Triangle交叉检测,主要是计算射线与三角形所构成的平面

3D空间中射线与轴向包围盒AABB的交叉检测算法【转】

引言 在上一节中,我讲述了如何实现射线与三角形的交叉检测算法.但是,我们应该知道,在游戏开发中,一个模型有很多的三角形构成,如果要对所有的物体,所有的三角形进行这种检测,就算现在的计算机运算能力,也是无法高效的完成.所以,我们需要通过其他的手段来提早剔除一些不可能发生交叉的物体,这种早退的思想,大量的运用在3D游戏技术中.在本篇文章中,我将像大家讲述如何实现射线与轴向包围盒AABB的交叉检测.如果读者不明白什么是轴向包围盒,请看这篇文章. Ray-AABB交叉检测算法 现如今,有很多的Ray-A

3D空间中射线与轴向包围盒AABB的交叉检测算法 【转】

http://blog.csdn.net/i_dovelemon/article/details/38342739 引言 在上一节中,我讲述了如何实现射线与三角形的交叉检测算法. 但是,我们应该知道,在游戏开发中,一个模型有很多的三角形构成,如果要对所有的物体,所有的三角形进行这种检测,就算现在的计算机运算能力,也是无法高 效的完成.所以,我们需要通过其他的手段来提早剔除一些不可能发生交叉的物体,这种早退的思想,大量的运用在3D游戏技术中.在本篇文章中,我将像大家讲 述如何实现射线与轴向包围盒A

2D和3D空间中计算两点之间的距离

自己在做游戏的忘记了Unity帮我们提供计算两点之间的距离,在百度搜索了下. 原来有一个公式自己就写了一个方法O(∩_∩)O~,到僵尸到达某一个点之后就向另一个奔跑过去 /// <summary> /// 3维中如何计算两点之间的距离 /// </summary> /// <param name="p1"></param> /// <param name="p2"></param> /// &l

Direct3D 11 Tutorial 4: 3D Spaces_Direct3D 11 教程4:3D空间

概述 在上一个教程中,我们在应用程序窗口的中心成功渲染了一个三角形. 我们没有太注意我们在顶点缓冲区中拾取的顶点位置. 在本教程中,我们将深入研究3D位置和转换的细节. 本教程的结果将是渲染到屏幕的3D对象. 虽然之前的教程侧重于将2D对象渲染到3D世界,但在这里我们展示了一个3D对象. 资源目录 (SDK root)\Samples\C++\Direct3D11\Tutorials\Tutorial04 Github仓库 3D空间 在上一个教程中,三角形的顶点被有策略地放置,以在屏幕上完美地对

OpenGl学习进程(9)在3D空间的绘制实例

    本节将演示在3D空间中绘制图形的几个简单实例:     (1)在3D空间内绘制圆锥体: #include <GL/glut.h> #include <math.h> #pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"") #define PI 3.1416 GLfloat xRot = 0; GLfloat yRot =