目的
VectorMath是一个Swift库,用于Mac和iOS,实现了常见的2D和3D向量和矩阵函数,对游戏或基于向量的图形很有用。
VectorMath利用Swift语言的功能,如函数和操作符重载以及结构方法,提供比大多数基于C、C++或Cocoa的图形API更优雅的接口。
VectorMath还提供了便捷的GLKit向量数学类型和函数的替换,这些类型和函数由于依赖联合类型而在Swift中尚未提供。
VectorMath是一个完全独立的库,仅依赖于Foundation框架。然而,它提供了可选的兼容性扩展,以便与UIKit、AppKit、SpriteKit和SceneKit进行互操作性。
VectorMath旨在高效,但尚未进行大量优化,还未利用Accelerate框架中特定架构的硬件加速。
支持的操作系统和SDK版本
- 支持的构建目标 - iOS 12.0,Mac OS 10.14 (Xcode 11.1)
- 最早支持的部署目标 - iOS 9.0,Mac OS 10.13
- 最早兼容的部署目标 - iOS 7.0,Mac OS 10.9
注意:“支持”意味着库已针对此版本进行过测试。“兼容”意味着库应在该操作系统版本上运行(即它不依赖于任何不可用的SDK功能),但不再进行兼容性测试,可能需要调整或错误修复才能正确运行。
安装
要在应用程序中使用 VectorMath 函数,将 VectorMath.swift 文件(无需演示文件和资源文件)拖入您的项目中。您还可能希望包括 VectorMath+SceneKit.swift 和/或 VectorMath+Quartz.swift 兼容性扩展。
类型
VectorMath 声明了以下类型
Scalar
这是一个类型别名,用于 VectorMath 库中的标量浮点值。默认设置为 Float,但您可以将其更改为 Double 或 CGFloat 以提高特定应用程序的性能。
Vector2
Vector3
Vector4
这些分别表示二维、三维和四维向量。
Matrix3
Matrix4
这些分别表示 3x3 和 4x4 的齐次变换矩阵。
Quaternion
这表示三维空间中的旋转。它具有与 Vector4D 相同的结构,但由于不同的使用案例和方法而被定义为不同的类型。
所有的 VectorMath 类型都符合 Equatable 和 Hashable,因此可以存储在 Swift 字典中。
常量
VectorMath 声明了一些方便使用的作用域名称常量。如下所示
Scalar.pi
Scalar.halfPi
Scalar.quarterPi
Scalar.twoPi
这些应该是自行说明的。
Scalar.degreesPerRadian
Scalar.radiansPerDegree
度数和弧度之间的转换系数。例如,要将 40 度转换为弧度,您可以说 let r = 40 * .degreesPerRadian
,或将 Pi/2 弧度转换为度,可以说 let d = .halfPi * .radiansPerDegree
Scalar.epsilon = 0.0001
这是由近似相等运算符使用的浮点错误值。如果您觉得不够精确(或过于精确),可以更改它。
Vector2.zero
Vector3.zero
Vector4.zero
Quaternion.Zero
这些是零向量常量,用作向量的默认值。
Vector2.x
Vector2.y
Vector3.x
Vector3.y
Vector3.z
Vector4.x
Vector4.y
Vector4.z
Vector4.w
这些是在各个轴上的单位向量。例如,Vector3.z 的值是 Vector3(0, 0, 1)
。
Matrix3.identity
Matrix4.identity
Quaternion.identity
这些是单位矩阵,其性质是乘以另一个矩阵或向量没有效果。
方法
完整的 VectorMath 属性和方法列表如下。这些大多可以自行说明。如果您找不到您要查找的方法(例如,使用四元数旋转向量的方法),它可能已作为运算符实现(见“运算符”以下)。
Vector2
init(x: Scalar, y: Scalar)
init(_: Scalar, _: Scalar)
init(_: [Scalar])
lengthSquared: Scalar
length: Scalar
inverse: Vector2
toArray() -> [Scalar]
dot(Vector2) -> Scalar
cross(Vector2) -> Scalar
normalized() -> Vector2
rotated(by: Scalar) -> Vector2
rotated(by: Scalar, around: Vector2) -> Vector2
angle(with: Vector2) -> Scalar
interpolated(with: Vector2, by: Scalar) -> Vector2
Vector3
init(x: Scalar, y: Scalar, z: Scalar)
init(_: Scalar, _: Scalar, _: Scalar)
init(_: [Scalar])
lengthSquared: Scalar
length: Scalar
inverse: Vector3
xy: Vector2
xz: Vector2
yz: Vector2
toArray() -> [Scalar]
dot(Vector3) -> Scalar
cross(Vector3) -> Vector3
normalized() -> Vector3
interpolated(with: Vector3, by: Scalar) -> Vector3
Vector4
init(x: Scalar, y: Scalar, z: Scalar, w: Scalar)
init(_: Scalar, _: Scalar, _: Scalar, _: Scalar)
init(_: Vector3, w: Scalar)
init(_: [Scalar])
lengthSquared: Scalar
length: Scalar
inverse: Vector4
xyz: Vector3
xy: Vector2
xz: Vector2
yz: Vector2
toArray() -> [Scalar]
toVector3() -> Vector3
dot(Vector4) -> Scalar
normalized() -> Vector4
interpolated(with: Vector4, by: Scalar) -> Vector4
Matrix3
init(m11: Scalar, m12: Scalar, ... m33: Scalar)
init(_: Scalar, _: Scalar, ... _: Scalar)
init(scale: Vector2)
init(translation: Vector2)
init(rotation: Scalar)
init(_: [Scalar])
adjugate: Matrix3
determinant: Scalar
transpose: Matrix3
inverse: Matrix3
toArray() -> [Scalar]
interpolated(with: Matrix3, by: Scalar) -> Matrix3
Matrix4
init(m11: Scalar, m12: Scalar, ... m33: Scalar)
init(_: Scalar, _: Scalar, ... _: Scalar)
init(scale: Vector3)
init(translation: Vector3)
init(rotation: Vector4)
init(quaternion: Quaternion)
init(fovx: Scalar, fovy: Scalar, near: Scalar, far: Scalar)
init(fovx: Scalar, aspect: Scalar, near: Scalar, far: Scalar)
init(fovy: Scalar, aspect: Scalar, near: Scalar, far: Scalar)
init(top: Scalar, right: Scalar, bottom: Scalar, left: Scalar, near: Scalar, far: Scalar)
init(_: [Scalar])
adjugate: Matrix4
determinant: Scalar
transpose: Matrix4
inverse: Matrix4
toArray() -> [Scalar]
interpolated(with: Matrix3, by: Scalar) -> Matrix3
Quaternion
init(x: Scalar, y: Scalar, z: Scalar, w: Scalar)
init(_: Scalar, _: Scalar, _: Scalar, _: Scalar)
init(axisAngle: Vector4)
init(pitch: Scalar, yaw: Scalar, roll: Scalar)
init(rotationMatrix m: Matrix4)
init(_: [Scalar])
lengthSquared: Scalar
length: Scalar
inverse: Quaternion
xyz: Vector3
pitch: Scalar
yaw: Scalar
roll: Scalar
toAxisAngle() -> Vector4
toPitchYawRoll() -> (pitch: Scalar, yaw: Scalar, roll: Scalar)
toArray() -> [Scalar]
dot(Quaternion) -> Scalar
normalized() -> Quaternion
interpolated(with: Quaternion, by: Scalar) -> Quaternion
运算符
VectorMath大量使用了运算符重载,但我尽量不过度使用自定义运算符。唯一的一个非标准运算符是 ~=
,表示"近似等于",这在比较标量、向量或矩阵值是否相等时非常有用,因为由于浮点数的不精确,它们很少完全相同。
*, /, +, -, 和 == 运算符实现了大多数包含的类型。特别是 * 对于矩阵和向量的变换非常有用。例如,要对向量“v”应用矩阵变换“m”,可以编写 m * v
。* 还可以与标量值一起使用来缩放向量。
支持对向量和矩阵的单目减法,用于求倒数或否定。
点积、叉积和归一化并不是作为运算符提供的,但在各种类型中作为方法提供。
致谢
VectorMath中使用的许多算法是从C语言的Kazmath向量数学库(https://github.com/Kazade/kazmath)移植或适配的,或者是从出色的矩阵和四元数FAQ(http://www.j3d.org/matrix_faq/matrfaq_latest.html)中派生出来的。
此外,以下人员直接为该项目做出了贡献
- @harlanhaskins - SPM和Linux支持
- @milpitas - CocoaPods支持
- @billhsu / @ismailbozk - 错误修复和测试覆盖率
- @jiropole - MapKit集成
- @nicklockwood - 其他一切
(贡献者完整列表)