说明

本文来自于我在 Let’s VisionOS 2024 大会上的演讲,原演讲内容分为两个方面:向量与矩阵基础知识手势匹配框架 HandVector。为了便于阅读,我对原演讲内容进行了调整与简化,改写为了两篇文章《只需三板斧!带你入门 visionOS 空间计算的数学与几何基础》和《我开源了个手势匹配框架,让你在模拟器调试 visionOS 手部追踪功能!》。

可在 此处 获得 Keynotes 的 PDF 版本。

正文

看不懂苹果 visionOS Demo 中的数学与几何运算?这是很多 iOS 开发者试图学习 visionOS 开发时遇到的最大困难。我周围也有很多人也试图去学习计算几何相关知识,但是却被相关书籍和视频教程陡峭的入门曲线吓退。

本质上,这是因为普通开发者缺少“敲门砖”与“三板斧”,导致难以入门。我自己作为一名 iOS 开发者,也曾面临这样的问题,所以我将 3D/AR 中基础的数学与几何运算做了整理,选出了向量与矩阵最常见的三种运算,做为入门学习的 “敲门砖”“三板斧”,带领大家顺利入门。为了形象说明运算的作用,我们将各种运算用图形化方式来呈现准确说明它们的几何意义,并对苹果 Demo 中的运算作用进行讲解,帮助大家更好入门。

坐标系,点与向量

在 RealityKit 中,我们使用的是右手系,也就是与右手的三根手指完美对应。

只需三板斧!带你入门 visionOS 空间计算的数学与几何基础

点与向量的定义

在这样一个坐标系中,一个变量 let a = simd_float3(1, 2, 3) ,它可以看作是一个点的位置,也可以当做一个向量,但是一但按规则进行运算后不可随意更改几何含义。

运算规定: 点与向量的运算规律如下:

  • vector + vector = vector
  • point – point = vector
  • point + vector = point
  • point + point = ?? => (point + point)/2 = middle point

从数学运算角度,为了统一进行运算会将其补成 4 维,点后面补 1,向量后面补 0:

3D point  = (x, y, z, 1)
3D vector = (x, y, z, 0)

同样,在 RealityKit 中,点与向量的转换函数也是不同的:

只需三板斧!带你入门 visionOS 空间计算的数学与几何基础

常用向量运算

常见向量运算三板斧:

  • 向量点乘:dot(a, b) => a b
  • 向量叉乘:cross(a, b) => a b
  • 向量归一化:normalize(a) => a/||a||

点乘的几何意义

  • 一个向量在另一个向量上的投影长
  • 点乘的大小也反映了两个向量有多“平行”,一般配合归一化(normalize)
  • 交换律:a b = b a
  • 分配律:a (b + c) = a b + a c
    只需三板斧!带你入门 visionOS 空间计算的数学与几何基础

比如,在苹果的 Demo SwiftSplash 中的吸附对齐功能,就是用点乘和归一化实现的:

只需三板斧!带你入门 visionOS 空间计算的数学与几何基础
具体的代码如下,先用位置坐标相减得到两个向量,然后将它们归一化之后再点乘,如果大于 0.95 或小于 -0.95 就会自动吸附。
只需三板斧!带你入门 visionOS 空间计算的数学与几何基础

叉乘的几何意义

  • 结果是一个新的向量,方向垂直于运算的两个向量,右手螺旋法则
  • 叉乘的大小也反映了两个向量有多“垂直”, 长度等于围成的平行四边形的面积
  • 反交换律:a b = – b a
  • 分配律:a (b + c) = a b + a c

只需三板斧!带你入门 visionOS 空间计算的数学与几何基础
叉乘在实际开发中一般有两个用途:1.用来求平面的法线,2.求向量围成的面积。比如在苹果 Demo Happy Beam 中,手势比心后,光柱的方向就是用叉乘来确定的。
只需三板斧!带你入门 visionOS 空间计算的数学与几何基础
其中,将大拇指根部连线作为 x 轴方向,将大拇指指尖到食指指尖方向作为 y 轴,叉乘后的负方向就是光柱的方向。
只需三板斧!带你入门 visionOS 空间计算的数学与几何基础

矩阵

  • 包含了坐标系的位置、朝向和大小信息
  • 具体有 xyz 轴的向量,及原点坐标
  • RealityKit 中 Entity 包含了矩阵信息

开发中一般使用 4×4 矩阵,它其实就是将坐标系的位置和坐标轴依次写下来:前三列分别是 XYZ 轴的向量,最后一列是原点的位置。其中向量后面补 0,而位置后面补 1,这样可以统一运算。

只需三板斧!带你入门 visionOS 空间计算的数学与几何基础
在苹果 Demo Happy Beam 中,也用到了从手部矩阵中获取位置的方法:matrix.colunms.3.xyz 就得到了矩阵的位置信息。
只需三板斧!带你入门 visionOS 空间计算的数学与几何基础
在对位置信息进行一系列运算后,重新得到了新的 XYZ 轴向量,以及中心点坐标,就可以重新合成得到比心的手势的矩阵。
只需三板斧!带你入门 visionOS 空间计算的数学与几何基础

常用矩阵运算

  • 矩阵乘法:m1 * m2
  • 矩阵的逆:m.inverse
  • 矩阵的反转(镜像):entity.scale *= .init(x: -1, y: 1, z: 1)

矩阵乘法 multiply

  • 类似盒子的嵌套
  • 用在不同层级物体之间,将子级坐标转换为父级坐标

只需三板斧!带你入门 visionOS 空间计算的数学与几何基础
假如在 Cube_1 中有一个点 a: (1, 2, 3) 那么它在 Cube_0 中的坐标为:matrix_cube_1 * (1, 2, 3, 1) 在 Root 中的坐标为:matrix_cube_0 * matrix_cube_1* (1, 2, 3, 1)

矩阵的逆 inverse

  • 一般用在同层级的物体之间
  • 将兄弟关系变成父子关系

只需三板斧!带你入门 visionOS 空间计算的数学与几何基础
比如,下面的例子,将橙色盒子中的坐标转换到紫色盒子中,就需要用到矩阵的逆:
只需三板斧!带你入门 visionOS 空间计算的数学与几何基础
假如在 Cube_1 中有一个点 a: (1, 2, 3) 那么它在 Cube_0 中的坐标为:matrix_cube_1 * (1, 2, 3, 1) 在 Cube_2 中的坐标为:matrix_cube_2.inverse * matrix_cube_1* (1, 2, 3, 1)

矩阵反转/镜像 reflection/mirror

  • 会将右手系变成左手系,同时造成内外表面反转
  • 除非明确了解矩阵反转的含义,否则不要轻易进行反转操作
  • 反转任意两根坐标轴,等同于绕不变的轴旋转 180 度
    只需三板斧!带你入门 visionOS 空间计算的数学与几何基础
    只需三板斧!带你入门 visionOS 空间计算的数学与几何基础
//左侧 Enity,反转 x 轴,造成了内外表面反转
entityLeft.scale *= .init(x: -1, y: 1, z: 1)
//右侧 Enity,反转 x 轴 和 y 轴,等同于绕 z 轴旋转 180 度
entityRight.scale *= .init(x: -1, y: -1, z: 1)

在苹果 Demo Hello World 中,星空背景就是用这种方式实现的。

只需三板斧!带你入门 visionOS 空间计算的数学与几何基础
相关代码如下,关键之处在于倒数第二行:
只需三板斧!带你入门 visionOS 空间计算的数学与几何基础

总结

掌握了向量运算三板斧+矩阵运算三板斧,无需再害怕空间计算中的数学公式。

只需三板斧!带你入门 visionOS 空间计算的数学与几何基础
更多关于 HandVector 的效果演示与计算讲解,请查看《我开源了个手势匹配框架,让你在模拟器调试 visionOS 手部追踪功能!》文章。

感谢主办方的精心组织,希望 Let’s VisionOS 活动未来更上一层楼。