3D数学基础 第二章:向量/矢量

向量是数学和物理学等领域中常见的概念,它是由大小(或称为模或长度)和方向组成的量。在二维空间中,向量通常表示为具有两个分量(x 和 y)的有序对 (x, y),在三维空间中则通常表示为具有三个分量(x、y 和 z)的有序三元组 (x, y, z)。

点积

向量之间的点积,也称为内积或数量积,是向量运算中的一种重要操作。给定两个 n 维向量 A 和 B,它们的点积(记作 A·B 或 <A, B>)定义为:

A·B = A₁ * B₁ + A₂ * B₂ + … + Aₙ * Bₙ

其中 A₁、A₂、…、Aₙ 和 B₁、B₂、…、Bₙ 分别表示向量 A 和 B 的各个分量。

点积的结果是一个标量(即一个实数),而不是一个向量。点积的计算方法是将两个向量对应分量相乘,然后将这些乘积相加得到一个标量。

点积有一些重要的性质:

  1. 交换律: A·B = B·A
  2. 分配律: A·(B + C) = A·B + A·C
  3. 结合律: k(A·B) = (kA)·B = A·(kB),其中 k 是一个标量(实数)
  4. 计算夹角: 如果 A 和 B 是非零向量,它们的夹角 θ 可以通过以下公式计算:cos(θ) = (A·B) / (|A| * |B|),其中 |A| 和 |B| 分别表示向量 A 和 B 的模(长度)。

相关性质及推导

  1. 交换律:A·B = B·A

从几何角度来看,点积 A·B 表示向量 A 在向量 B 方向上的投影与向量 B 的长度的乘积(即BAcosθ)。而点积 B·A 表示向量 B 在向量 A 方向上的投影与向量 A 的长度的乘积(即ABcosθ)。由于投影的长度与投影方向无关,所以 A·B 和 B·A 的结果相同。

  1. 结合律 k(A·B) = (kA)·B = A·(kB),其中 k 是一个标量(实数)
    我们假设有两个二维向量 A 和 B,以及标量 k。它们的分量分别为 A₁、A₂ 和 B₁、B₂。

    首先,我们来看 k(A·B) 的计算过程,它表示向量 A 在向量 B 方向上的投影与向量 B 的长度的乘积再乘以标量 k。

    1. 计算向量 B 的长度:
      |B| = √(B₁² + B₂²)

    2. 计算向量 A 在向量 B 方向上的投影:
      A 在向量 B 方向上的投影 = |A| * cos(θ₁)

      其中 θ₁ 表示向量 A 与向量 B 之间的夹角,可以通过点积的计算得到:

      cos(θ₁) = (A·B) / (|A| * |B|)

      代入 A 在向量 B 方向上的投影的计算式:

    A 在向量 B 方向上的投影 = |A| * ((A·B) / (|A| * |B|))

    1. 现在,我们将 A 在向量 B 方向上的投影乘以标量 k:
      k(A 在向量 B 方向上的投影) = k * (|A| * ((A·B) / (|A| * |B|))) = (kA)·B

      这里我们引入了向量 kA,它是向量 A 的每个分量都乘以标量 k 后得到的向量。

    2. 接下来,我们来计算 (kA)·B,这表示向量 kA 在向量 B 方向上的投影。
      (kA) 在向量 B 方向上的投影 = |kA| * cos(θ₂)

      其中 θ₂ 表示向量 kA 与向量 B 之间的夹角,可以通过点积的计算得到:

    cos(θ₂) = ((kA)·B) / (|kA| * |B|)

    因为 |kA| = |k| * |A|,所以:

    ((kA)·B) / (|kA| * |B|) = ((kA)·B) / (|k| * |A| * |B|)

    代入 (kA) 在向量 B 方向上的投影的计算式:

    (kA) 在向量 B 方向上的投影 = |kA| * ((kA)·B) / (|k| * |A| * |B|) = |k| * |A| * ((kA)·B) / (|k| * |A| * |B|) = k * (A·B)

    1. 最后,我们将向量 kA 在向量 B 方向上的投影与向量 B 的长度相乘,得到 (kA)·B 的结果:
      (kA)·B = |kA| * ((kA)·B) / (|k| * |A| * |B|) = k * (A·B)

    综上所述,我们得到 k(A·B) = (kA)·B,其中向量 kA 是向量 A 的每个分量都乘以标量 k 后得到的向量。同时,我们也得到 k(A·B) = A·(kB),其中向量 kB 是向量 B 的每个分量都乘以标量 k 后得到的向量。这就是点积的结合律的几何推导过程。

叉积

与点积不同,叉积的结果是一个新的向量,而不是一个标量。叉积通常在三维空间中定义,用来计算两个向量之间垂直于它们所在平面的向量。

给定两个三维向量 A = (A₁, A₂, A₃) 和 B = (B₁, B₂, B₃),它们的叉积为C(记作 A × B)定义为:

C₁ = A₂ * B₃ - A₃ * B₂ ``C₂ = A₃ * B₁ - A₁ * B₃ ``C₃ = A₁ * B₂ - A₂ * B₁

其中 A₁、A₂、A₃ 和 B₁、B₂、B₃ 分别表示向量 A 和 B 的三个分量。

**叉积的结果是一个新的向量,它垂直于原来的两个向量所在的平面,并且方向满足右手法则。**右手法则用来确定结果向量的方向:将右手的食指指向向量 A 的方向,将中指指向向量 B 的方向,然后拇指的方向就是结果向量的方向。

叉积有一些重要的性质:

  1. 反交换律: A × B = - (B × A),即叉积不满足交换律,其结果方向与顺序有关。
  2. 分配律: A × (B + C) = A × B + A × C,即叉积满足分配律,可以在展开后分别计算再相加。
  3. 结合律: 叉积没有结合律,即 (A × B) × C 不等于 A × (B × C)。
  4. 共线性: 如果两个向量 A 和 B 共线(即平行或反向),则它们的叉积结果为零向量。

应用

  1. 将一个向量 V 分解为与另一个向量 U 垂直和水平的分量
    通常采用向量投影的方法。首先,来计算 V 在 U 方向上的投影,即 V 在 U 方向上的垂直分量。然后,我们可以通过减去这个投影向量,得到 V 在 U 方向上的水平分量。

    步骤如下:

    1. 如果 U 不是单位向量,计算 U 的单位向量 U’,即将 U 除以它的模(长度),得到长度为 1 的向量 U’( U’ = U / |U| )。
    2. 计算 V 在 U 方向上的投影 P,即 V 在 U’ 方向上的投影。投影 P = V·U’。
    3. 计算垂直分量 Vv,即 V 在 U 方向上的垂直分量:Vv = P * U’。
    4. 计算水平分量 Vh,即 V 减去垂直分量的结果:Vh = V - Vv。
  2. 确定NPC与玩家的相对位置

    1. 游戏中的npc站在P位置,方向为V,玩家在X,确定NPC在X的前面还是后面

      1. 首先,计算玩家到NPC的向量 D,即 D = P - X。这个向量表示从玩家位置指向NPC位置的方向。
      2. 计算向量 D 和朝向向量 V 的夹角 θ。夹角可以通过计算向量的点积来得到,点积公式如下:
        D · V = |D| * |V| * cos(θ)
        其中,· 表示向量的点积,|D| 表示向量 D 的模(长度),|V| 表示向量 V 的模,θ 是向量 D 和 V 的夹角。
      3. 通过上面的公式可以解出 cos(θ):cos(θ) = (D · V) / (|D| * |V|)
      4. 如果 cos(θ) 大于 0,则表示夹角 θ 处于 0 到 90 度之间,NPC在玩家的前面。如果 cos(θ) 小于 0,则表示夹角 θ 处于 90 到 180 度之间,NPC在玩家的后面,如果等于0,说明玩家在npc的正左边或者右边。
    2. 设p=[-3 4]且v=[5 -2]。对于以下每个点x是在NPC的前面还是后面。
      (1) x=[0 0]
      (2) x=[1 6]

      1. x = [0, 0]
        向量 D=px=[3,4][0,0]=[3,4]\mathbf{D} = \mathbf{p} - \mathbf{x} = [-3, 4] - [0, 0] = [-3, 4]

        cos(θ)=DvDv=(35+4(2))(3)2+4252+(2)2=(158)9+1625+4=2355<0cos(\theta) = \frac{\mathbf{D} \cdot \mathbf{v}}{|\mathbf{D}| |\mathbf{v}|} = \frac{(-3\cdot5 + 4\cdot(-2))}{\sqrt{(-3)^2 + 4^2} \sqrt{5^2 + (-2)^2}} = \frac{(-15 - 8)}{\sqrt{9 + 16} \sqrt{25 + 4}} = \frac{-23}{5 \sqrt{5}} < 0
      2. x = [1, 6]
        向量D=px=[3,4][1,6]=[4,2]\mathbf{D} = \mathbf{p} - \mathbf{x} = [-3, 4] - [1, 6] = [-4, -2]

        cos(θ)=DvDv=(45+(2)(2))(4)2+(2)252+(2)2=(20+4)16+425+4=16229<0\cos(\theta) = \frac{\mathbf{D} \cdot \mathbf{v}}{|\mathbf{D}| |\mathbf{v}|} = \frac{(-4\cdot5 + (-2)\cdot(-2))}{\sqrt{(-4)^2 + (-2)^2} \sqrt{5^2 + (-2)^2}} = \frac{(-20 + 4)}{\sqrt{16 + 4} \sqrt{25 + 4}} = \frac{-16}{2 \sqrt{29}} < 0
  3. 在题2的条件下,考虑NPC的视场(Field of View,FOV)受限的情况。如果总FOV角是θ,则NPC可以在其向前方向的左侧或右侧能看到的最大角度是θ/2。如何使用点积来确定点x是否对NPC可见?

考虑NPC的视场(Field of View, FOV)受限的情况下,我们可以使用点积来确定一个点 x 是否对NPC可见。具体方法如下:

  • 计算向量 D,即从NPC位置指向点 x 的向量。即 D=xpD = \mathbf{x} - \mathbf{p},其中 p 是NPC的位置。

  • 计算向量 D 和NPC的朝向向量 V 之间的夹角 θ。使用点积公式计算夹角:cos(θ)=DVDV\cos(\theta) = \frac{\mathbf{D} \cdot \mathbf{V}}{|\mathbf{D}| |\mathbf{V}|}

  • 如果cos(θ)cos(FOV2)\cos(\theta) \geq \cos(\frac{\text{FOV}}{2}),则表示点 x 对NPC可见。否则,点 x 不在NPC的视场范围内,对NPC不可见。

    总结:

  • 点 x 在NPC的FOV范围内,即cos(θ)cos(FOV2)\cos(\theta) \geq \cos(\frac{\text{FOV}}{2})

  • 点 x 与NPC的距离小于等于最大观察距离。

    如果以上两个条件同时满足,那么点 x 对NPC可见。否则,点 x 不在NPC的视野范围内或距离过远,对NPC不可见。

  1. 考虑在我们的左手坐标系的xz平面中标记为a、b和c的3个点,它们代表NPC路径上的航点(Waypoint)。

    1. 当从上方观察路径时,如何使用叉积来确定,NPC从a移动到b再移动到c时,应该顺时针还是逆时针转向b?
      使用叉积判断转向为顺时针还是逆时针:

      1. 首先,计算向量 AB 和向量 BC。向量 AB 表示从点 a 指向点 b 的向量,向量 BC 表示从点 b 指向点 c 的向量。

        AB×BC=(ABxBCzABzBCx)\mathbf{AB} \times \mathbf{BC} = (AB_x \cdot BC_z - AB_z \cdot BC_x) AB×BC\mathbf{AB} \times \mathbf{BC}
      2. 如果 **

        AB×BC\mathbf{AB} \times \mathbf{BC}
      3. 这样,通过计算向量的叉积,我们可以确定NPC在从 a 移动到 b 再移动到 c 的路径上应该选择顺时针还是逆时针转向 b。

    2. 对于以下3组中的每一组,确定当NPC从a移动到b再移动到e时,它应该顺时针还是逆时针转向。

    • a=[2,0,3]b=[1,0,5]e=[4,0,1]\mathbf{a} = [2, 0, 3],\mathbf{b} = [-1, 0, 5],\mathbf{e} = [-4, 0, 1] AB=ba=[1,0,5][2,0,3]=[3,0,2]\mathbf{AB} = \mathbf{b} - \mathbf{a} = [-1, 0, 5] - [2, 0, 3] = [-3, 0, 2] BE=eb=[4,0,1][1,0,5]=[3,0,4]\mathbf{BE} = \mathbf{e} - \mathbf{b} = [-4, 0, 1] - [-1, 0, 5] = [-3, 0, -4] AB×BE=(ABx×BEzABz×BEx)=(3×42×3)=6\mathbf{AB} \times \mathbf{BE} = (AB_x \times BE_z - AB_z \times BE_x) = (-3 \times -4 - 2 \times -3) = -6 由于 AB×BE\mathbf{AB} \times \mathbf{BE} 的结果为负值 (-6),NPC在从 a 移动到 b 再移动到 e 时应该选择顺时针转向。
    • a=[3,0,5]b=[4,0,0]e=[3,0,3]\mathbf{a} = [-3, 0, -5],\mathbf{b} = [4, 0, 0],\mathbf{e} = [3, 0, 3] AB=ba=[4,0,0][3,0,5]=[7,0,5]\mathbf{AB} = \mathbf{b} - \mathbf{a} = [4, 0, 0] - [-3, 0, -5] = [7, 0, 5] BE=eb=[3,0,3][4,0,0]=[1,0,3]\mathbf{BE} = \mathbf{e} - \mathbf{b} = [3, 0, 3] - [4, 0, 0] = [-1, 0, 3] AB×BE=(ABx×BEzABz×BEx)=(7×35×1)=26\mathbf{AB} \times \mathbf{BE} = (AB_x \times BE_z - AB_z \times BE_x) = (7 \times 3 - 5 \times -1) = 26 由于 AB×BE\mathbf{AB} \times \mathbf{BE} 的结果为正值 (26),NPC在从 a 移动到 b 再移动到 e 时应该选择逆时针转向。
    • a=[1,0,4]b=[7,0,1]e=[5,0,6]\mathbf{a} = [1, 0, 4],\mathbf{b} = [7, 0, -1],\mathbf{e} = [-5, 0, -6] AB=ba=[7,0,1][1,0,4]=[6,0,5]\mathbf{AB} = \mathbf{b} - \mathbf{a} = [7, 0, -1] - [1, 0, 4] = [6, 0, -5] BE=eb=[5,0,6][7,0,1]=[12,0,5]\mathbf{BE} = \mathbf{e} - \mathbf{b} = [-5, 0, -6] - [7, 0, -1] = [-12, 0, -5] AB×BE=(ABx×BEzABz×BEx)=(6×5(5)×12)=30\mathbf{AB} \times \mathbf{BE} = (AB_x \times BE_z - AB_z \times BE_x) = (6 \times -5 - (-5) \times -12) = 30 由于 AB×BE\mathbf{AB} \times \mathbf{BE} 的结果为正值 (30),NPC在从 a 移动到 b 再移动到 e 时应该选择逆时针转向。

3D数学基础 第二章:向量/矢量
https://jing-jiu.github.io/jing-jiu/2023/07/31/notebooks/3D数学基础:图形和游戏开发/第二章:向量/
作者
Jing-Jiu
发布于
2023年7月31日
许可协议