说明
简单地说,3D 计算几何(Computational Geometry)就是计算 3D 空间中,点到直线距离,直线与平面交点等几何位置和关系的算法。对于普通开发者来说很少用到,但对于 3D/AR 开发者来说,却是经常遇到类似问题。虽然 3D 引擎一般都提供了内置的一些功能帮忙我们计算位置和姿态,但偶尔还是需要用到计算几何的知识。
本系列文章,就是讲解在工程中类似问题的解法,并提供 Swift 版代码以供参考。
基本约定
计算几何常用的数据结构是:向量、矩阵、四元数。常用的运算是:向量点乘、向量叉乘、矩阵乘法、矩阵逆运算、四元数乘法。
需要说明的是,计算几何算法通常是与左/右手系无关的,也和列主序/行主序矩阵表示方法无关。但为了简单方便,本系列代码和示意图,将使用右手系和列主序矩阵(与 ARKit 中相同)。
基础知识
本系列中,我将使用 Swift 语言中的 simd 框架来表示这些数据,运算函数也是 simd 框架内置的。数据类型使用单精度浮点数Float
类型。
还需要说明的是,受限于Float
类型精度限制,某些解法可能存在误差,也就是说按照数学原理,点A是不在平面上的, 但按我们的算法得出点 A 在平面上(误差范围内)。对于这种情况,我们项目中一般不做处理,不花费时间精力强行保持数学正确性。
向量 Vector,点 Point
在 simd 中,我们使用simd_float3
或SIMD3<Float>
来代表三维向量和点。它们之间的关系如图:
另外需要注意的是,当向量/点与矩阵运算时,通常会使用齐次坐标,也就是从simd_float3
变成simd_float4
,对于点后面需要补 1,而向量后面补 0,因为点会受到平移的影响,而向量不会:
// 点后面补 1,成为齐次坐标形式
let point3 = simd_float3(1, 1, 1)
let point4 = simd_float4(point3, 1)
// 向量后面补 0,成为齐次坐标形式
let vector3 = simd_float3(1, 1, 1)
let vector4 = simd_float4(vector3, 0)
- 点乘:也叫点积,函数名
dot
,通常用来计算两个向量夹角,是否平行/垂直,还可以计算一个向量在另一个向量方向上的投影长。 - 叉乘:也叫叉积,函数名
cross
,通常用来计算两个向量的旋转轴方向,组成平面的法线,组成平行四边行的面积大小。
矩阵 Matrix
矩阵一般使用simd_float4x4
或matrix_float4x4
,初始化的时候是将列向量一行一行写的,所以下面的矩阵其实是按列排列的:
let _ = simd_float4x4(simd_float4(1, 0, 0, 0),//第 0 列
simd_float4(0, 2, 0, 0),//第 1 列
simd_float4(0, 0, 3, 0),
simd_float4(4, 5, 6, 1)
)
如下图,矩阵的各列分别代表了运动后的坐标轴位置和原点位置:
矩阵可以表示运动,那么逆矩阵则表示相反的运动(即回到原始状态)。矩阵的乘法表示连续的运动。矩阵乘法只有一种,所以可以直接用乘法运算符
*
表示,也可以用函数matrix_multiply
或simd_mul
表示。
注意:因为矩阵是列主序,所以矩阵与向量相乘时,矩阵在左侧,点在右侧。几何含义是:将点按照矩阵进行运动(变换)。 如果点写在了左侧,那么相当于将矩阵转置后再左乘:
let m = matrix_float4x4(simd_float4(1, 0, 0, 0),//第 0 列
simd_float4(0, 2, 0, 0),//第 1 列
simd_float4(0, 0, 3, 0),
simd_float4(4, 5, 6, 1)
)
// 将点按矩阵 m 进行变换(运动)
let transformPoint = m * simd_float4(point, 1) //(5.0, 9.0, 15.0, 1.0)
// 以下两种写法等同
let transformPoint2 = simd_float4(point, 1) * m //(1.0, 4.0, 9.0, 33.0)
let transfromPoint3 = m.transpose * simd_float4(point, 1) //(1.0, 4.0, 9.0, 33.0)
四元数 Quaternion
四元数使用simd_quatf
类型,它代表了旋转,四元数乘法代表了连续的旋转。
四元数乘法中,应用顺序与矩阵不同:
- 矩阵 A * B 代表:先进行 B 运动,再进行 A 运动;
- 四元数 a * b 代表:先进行 a 旋转,再进行 b 旋转;
参考资料
本系列文章代码已发布在 github:ComputationalGeometrySwift
- 《计算机图形学几何工具算法详解》
- 《3D游戏与计算机图形学中的数学方法》 第3版
- 《3D数学基础图形与游戏开发》 第2版