游戏开发中的进阶向量数学
游戏开发中的进阶向量数学
- 飞机
- 到飞机的距离
- 远离原点
- 以2D方式构建平面
- 飞机的一些例子
- 3D碰撞检测
- 更多信息
飞机
点积具有带有单位向量的另一个有趣的属性。想象一下,垂直于该矢量(并通过原点)的平面通过了一个平面。平面将整个空间分为正数(在平面上)和负数(在平面下),并且(与流行的看法相反),您还可以在2D中使用其数学运算:
垂直于曲面的单位向量(因此,它们描述了曲面的方向)称为单位法向向量。虽然,通常他们只是简称为法线。法线出现在飞机,3D几何(以确定其中每一个面或顶点板壁)等。通常 是一个单位矢量,但它被称为正常 ,因为它的用法。(就像我们将(0,0)称为原点)。
看起来很简单。平面经过原点,并且其表面垂直于单位矢量(或法线)。指向向量的一侧为正半空间,而另一侧为负半空间。在3D中,这是完全相同的,除了平面是一个无限的表面(想象一个可以定向并固定到原点的无限的平纸)而不是一条线。
到飞机的距离
现在很清楚飞机是什么,让我们回到点积。单位矢量和空间中任何点之间的点积 (是的,这次我们进行矢量和位置之间的点积),返回从点到平面的距离:
var distance = normal.Dot(point);
但是不仅是绝对距离,如果点在负半空间中,则距离也将为负:
这使我们能够知道一个点在平面的哪一侧。
远离原点
我知道你在想什么!到目前为止,这还不错,但是真实的飞机在空间中无处不在,不仅经过原点。你想真正的飞机的行动,你想它现在。
请记住,平面不仅将空间分成两部分,而且还具有极性。这意味着可以有完全重叠的平面,但是它们的负半空间和正半空间会互换。
考虑到这一点,让我们将整个平面描述为法线 N和距原点标量D的 距离。因此,我们的平面由N和D表示。例如:
对于3D数学,Godot提供了Plane 内置类型来处理。
基本上,N和D可以表示空间中的任何平面,无论是2D还是3D(取决于N的维数),并且两者的数学公式相同。与以前相同,但是D是从原点到平面的距离,沿N方向行进。例如,假设您想到达飞机上的某个点,您将执行以下操作:
var pointInPlane = N * D;
这将拉伸(调整大小)法线向量并使之接触平面。这个数学运算看起来似乎很混乱,但是实际上比看起来要简单得多。如果我们想再次说出点到平面的距离,我们可以做同样的事情,只是要调整距离:
var distance = N.Dot(point) - D;
使用内置函数的相同操作:
var distance = plane.DistanceTo(point);
这将再次返回正或负距离。
可以通过使N和D都为负值来翻转平面的极性。这将导致平面处于相同的位置,但是具有负半角和正半角的反转:
N = -N;
D = -D;
当然,Godot也可以在Plane中实现此运算符,因此请执行以下操作:
var invertedPlane = -plane;
将按预期工作。
因此,请记住,飞机就是这样,它的主要实际用途是计算到它的距离。那么,为什么计算点到平面的距离有用呢?这非常有用!让我们看一些简单的例子。
以2D方式构建平面
平面显然不会从任何地方冒出来,因此必须进行构建。以2D方式构建它们很容易,可以从法线(单位矢量)和一个点,也可以从空间中的两个点完成。
对于法线和点,由于已经计算了法线,因此大部分工作都已完成,因此只需根据法线和点的点积计算D。
var N = normal;
var D = normal.Dot(point);
对于空间中的两个点,实际上有两个平面穿过它们,它们共享相同的空间,但法线指向相反的方向。要从两点计算法线,必须首先获取方向矢量,然后将其向任一侧旋转90°度:
// Calculate vector from `a` to `b`.
var dvec = (pointB - pointA).Normalized();
// Rotate 90 degrees.
var normal = new Vector2(dvec.y, -dvec.x);
// Alternatively (depending the desired side of the normal):
// var normal = new Vector2(-dvec.y, dvec.x);
其余部分与前面的示例相同,因为point_a或point_b都在同一平面上,所以它们都可以工作:
var N = normal;
var D = normal.Dot(pointA);
// this works the same
// var D = normal.Dot(pointB);
在3D模式下执行相同的操作会稍微复杂一些,将在后面进行详细说明。
飞机的一些例子
这是平面有用的简单示例。假设您有一个凸 多边形。例如,矩形,梯形,三角形或没有面向内弯曲的任何多边形。
对于多边形的每个片段,我们都会计算经过该片段的平面。一旦有了平面列表,我们就可以做整齐的事情,例如检查点是否在多边形内。
我们遍历所有平面,如果可以找到到该点的距离为正的平面,则该点在多边形之外。如果我们做不到,那么重点就在里面。
代码应该是这样的:
var inside = true;
foreach (var p in planes)
{// check if distance to plane is positiveif (p.DistanceTo(point) > 0){inside = false;break; // with one that fails, it's enough}
}
太酷了吧?但这会变得更好!稍加努力,当两个凸多边形也重叠时,类似的逻辑就会让我们知道。这称为分离轴定理(或SAT),大多数物理引擎都使用它来检测碰撞。
对于一个点,仅检查飞机是否返回正距离就足以确定该点是否在外面。对于另一个多边形,我们必须找到一个平面,在该平面上所有 其他多边形点都将 返回一个正距离。该检查是使用A的平面相对于B的点进行的,然后使用B的平面相对于A的点进行的:
代码应该是这样的:
var overlapping = true;foreach (Plane plane in planesOfA)
{var allOut = true;foreach (Vector3 point in pointsOfB){if (plane.DistanceTo(point) < 0){allOut = false;break;}}if (allOut){// a separating plane was found// do not continue testingoverlapping = false;break;}
}if (overlapping)
{// only do this check if no separating plane// was found in planes of Aforeach (Plane plane in planesOfB){var allOut = true;foreach (Vector3 point in pointsOfA){if (plane.DistanceTo(point) < 0){allOut = false;break;}}if (allOut){overlapping = false;break;}}
}if (overlapping)
{GD.Print("Polygons Collided!");
}
如您所见,飞机非常有用,这是冰山一角。您可能想知道非凸多边形会发生什么。通常可以通过将凹面多边形拆分为较小的凸面多边形,或使用诸如BSP(如今已不多使用)之类的技术来处理。
3D碰撞检测
这是另外一个奖励,是对耐心和遵守本篇教程的奖励。这是另一个智慧。这可能不是直接用例(Godot已经很好地进行了碰撞检测),但是几乎所有物理引擎和碰撞检测库都在使用它:)
还记得将2D中的凸形转换为2D平面数组对于碰撞检测很有用吗?您可以检测点是否在任何凸形形状内,或者两个2D凸形形状是否重叠。
好吧,这也适用于3D,如果两个3D多面体形状发生碰撞,您将无法找到分离平面。如果找到分离平面,则形状绝对不会碰撞。
要稍微刷新一点,一个分离平面意味着多边形A的所有顶点都在该平面的一侧,而多边形B的所有顶点都在另一侧。该平面始终是面A或面B的端面之一。
但是在3D中,这种方法存在问题,因为在某些情况下可能找不到分离平面。这是这种情况的一个示例:
为了避免这种情况,需要测试一些额外的平面作为分隔符,这些平面是面A的边与面B的边之间的叉积。
所以最终的算法是这样的:
var overlapping = true;foreach (Plane plane in planesOfA)
{var allOut = true;foreach (Vector3 point in pointsOfB){if (plane.DistanceTo(point) < 0){allOut = false;break;}}if (allOut){// a separating plane was found// do not continue testingoverlapping = false;break;}
}if (overlapping)
{// only do this check if no separating plane// was found in planes of Aforeach (Plane plane in planesOfB){var allOut = true;foreach (Vector3 point in pointsOfA){if (plane.DistanceTo(point) < 0){allOut = false;break;}}if (allOut){overlapping = false;break;}}
}if (overlapping)
{foreach (Vector3 edgeA in edgesOfA){foreach (Vector3 edgeB in edgesOfB){var normal = edgeA.Cross(edgeB);if (normal.Length() == 0){continue;}var maxA = float.MinValue; // tiny numbervar minA = float.MaxValue; // huge number// we are using the dot product directly// so we can map a maximum and minimum range// for each polygon, then check if they// overlap.foreach (Vector3 point in pointsOfA){var distance = normal.Dot(point);maxA = Mathf.Max(maxA, distance);minA = Mathf.Min(minA, distance);}var maxB = float.MinValue; // tiny numbervar minB = float.MaxValue; // huge numberforeach (Vector3 point in pointsOfB){var distance = normal.Dot(point);maxB = Mathf.Max(maxB, distance);minB = Mathf.Min(minB, distance);}if (minA > maxB || minB > maxA){// not overlapping!overlapping = false;break;}}if (!overlapping){break;}}
}if (overlapping)
{GD.Print("Polygons Collided!");
}
更多信息
有关在Godot中使用向量数学的更多信息,请参见以下文章:
矩阵与变换
如果您需要其他说明,请查看3Blue1Brown的精彩视频系列“线性代数的本质”:https://www.youtube.com/watch?v=fNk_zzaMoSs&list=PLZHQObOWTQDPD3MizzM2xVFitgF8hE_ab
游戏开发中的进阶向量数学相关推荐
- Unity游戏开发中的向量运算-点乘和叉乘
Unity游戏开发中的向量运算-点乘和叉乘 1.点乘: 定义: 又称点积.数量积.标量积.既可以由向量坐标的代数运算得出,也可以通过引入两个向量的长度和角度等几何概念来求解. 公式一: 公式二: 点积 ...
- 游戏开发中必备的数学知识(一)——向量
3D空间中的向量 向量:只有长度和方向,不含有位置信息的量,也就是说,两个向量只要长度和方向相同,则二者相同. 左手坐标系和右手坐标系 同样是三维的坐标系,两者的差别在Z轴上面.在左手坐标系中,Z轴正 ...
- 游戏开发中的数学、向量的应用
点 数学中的坐标系统(笛卡尔坐标系统) 这里A(0,0), B(1,2), C(4,3), D(–1,2), E(–2,–1), F(3,–2). 计算机中的坐标系统(屏幕坐标系统) 注意这里的y轴在 ...
- 游戏开发中的数学和物理算法10-18
1.标量 标量只有大小没有方向. 2.矢量 矢量既有大小又有方向. 3.常用举例: 物理上常用的矢量与标量的对应概念有:速度和速率:距离和位移等.如图: 距离: 假设A到B的距离为a,B到C的距离为b ...
- [Unity游戏开发]向量在游戏开发中的应用(一)
本文已同步发表在博客园:http://www.cnblogs.com/davidsheh/p/5246213.html ---------------------------------------- ...
- 向量在游戏开发中的应用(一)
向量在游戏开发中是非常实用的,我们在学校学完向量的知识后,只知道向量的基本知识,但对于如何将所学到的向量知识运用到实际的游戏开发中却不知所措.我计划写几篇关于向量在游戏中的应用的文章,总结一下在实际工 ...
- 矩阵在游戏开发中的应用
矩阵在游戏开发中的平移变换: 刚开始看3D数学学了矩阵之后并不明白他在游戏中的实际应用到底是怎么回事. 比如(1,0,0)可以表示一个点,也可以表示一个向量,当作为一个点沿x轴平移一个单位之后他的结果 ...
- 3D游戏开发中的矩阵详解
矩阵很多同学没有接触过,所以感觉很难,很复杂,其实只要学过矩阵的同学都知道,矩阵运算并不难.今天我们给大家讲讲游戏开发中的矩阵的运算. 这里有个游戏开发交流小组 大家可以一起来学习交流哦 1:矩阵是什 ...
- 游戏开发中的矩阵与变换
游戏开发中的矩阵与变换 介绍 矩阵组件和恒等矩阵 缩放转换矩阵 旋转变换矩阵 变换矩阵的基础 翻译转换矩阵 全部放在一起 剪切变换矩阵(高级) 转换的实际应用 在转换之间转换位置 相对于自身移动对象 ...
最新文章
- Spring/SpringBoot常用注解总结
- linux tree命令源码,[转帖]linux tree命令--显示目录的树形结构
- NOIP模拟测试5「星际旅行·砍树·超级树」
- 现代软件工程系列 学生读后感 梦断代码 布鲁克斯法则
- 腾讯云对象存储 python_GitHub - fushall1104/cos-python3-sdk: 腾讯云对象存储服务(cos)Python3.5版本SDK...
- pythonwindow程序窗体操作_python操作Windows窗口程序
- 新买的Olmpus 7070,5.1照得几张照片
- windows ce操作系统能用哪个导航_微软的windows和苹果的mac操作系统,在技术难度上哪个更高...
- spring 整合 JUnit(spring 内单元测试类调用带注入的报空指针异常NullPointException)
- itop4412的安卓驱动移植
- 安装前端插件 FeHelper
- matlab绘制柱状图语句,matlab绘制柱状图
- 读书感受 之 《如何说客户才会听,怎么听客户才肯说》
- odoo学习笔记(一)
- 07-20210305在WIN10下通过USB口给华为海思Hi3516DV300刷机(鸿蒙系统)
- TokenInsight 对话首席——隐私安全计算,价值几何?
- RGB565,RGB555, RGB888,RGB32转换
- AI自动修复图片网站
- 计算机图形学:二维图形的几何变换(算法原理及代码实现)
- 可以自动采集的小说网站程序源码