The Skung Rockification of Ziggy Skungdust and the SIMD's
This commit is contained in:
62
Sources/Maths/FloatExtensions.swift
Normal file
62
Sources/Maths/FloatExtensions.swift
Normal file
@ -0,0 +1,62 @@
|
||||
import Foundation
|
||||
|
||||
|
||||
public extension FloatingPoint
|
||||
{
|
||||
@inline(__always) var saturate: Self { min(max(self , 0), 1) }
|
||||
|
||||
@inline(__always) static func lerp(_ a: Self, _ b: Self, _ x: Self) -> Self { a * (1 - x) + b * x }
|
||||
|
||||
@inline(__always) static func deg(fromRad: Self) -> Self { fromRad * (180 / Self.pi) }
|
||||
@inline(__always) static func rad(fromDeg: Self) -> Self { fromDeg * (Self.pi / 180) }
|
||||
|
||||
@inline(__always) func smoothStep() -> Self
|
||||
{
|
||||
let x = self.saturate
|
||||
return x * x * (3 - 2 * x)
|
||||
}
|
||||
|
||||
func smoothStep(_ a: Self, _ b: Self) -> Self
|
||||
{
|
||||
let x = self.smoothStep()
|
||||
return b * x + a * (1 - x)
|
||||
}
|
||||
|
||||
@inline(__always) func smootherStep() -> Self
|
||||
{
|
||||
let x = self.saturate
|
||||
return x * x * x * (x * (x * 6 - 15) + 10)
|
||||
}
|
||||
|
||||
func smootherStep(_ a: Self, _ b: Self) -> Self
|
||||
{
|
||||
let x = self.smootherStep()
|
||||
return b * x + a * (1 - x)
|
||||
}
|
||||
|
||||
func sqrInterp(_ a: Self, _ b: Self) -> Self
|
||||
{
|
||||
let x = self.saturate, xx = x * x
|
||||
return a * (1 - xx) + b * xx
|
||||
}
|
||||
|
||||
func invSqrInterp(_ a: Self, _ b: Self) -> Self
|
||||
{
|
||||
let x = 1 - self.saturate, xx = x * x
|
||||
return a * xx + b * (1 - xx)
|
||||
}
|
||||
}
|
||||
|
||||
extension FloatingPoint where Self == Double
|
||||
{
|
||||
@inline(__always) var sine: Self { sin(self) }
|
||||
@inline(__always) var cosine: Self { cos(self) }
|
||||
@inline(__always) var tangent: Self { tan(self) }
|
||||
}
|
||||
|
||||
extension FloatingPoint where Self == Float
|
||||
{
|
||||
@inline(__always) var sine: Self { sinf(self) }
|
||||
@inline(__always) var cosine: Self { cosf(self) }
|
||||
@inline(__always) var tangent: Self { tanf(self) }
|
||||
}
|
99
Sources/Maths/Matrix3x3.swift
Normal file
99
Sources/Maths/Matrix3x3.swift
Normal file
@ -0,0 +1,99 @@
|
||||
#if USE_SIMD
|
||||
import simd
|
||||
#endif
|
||||
|
||||
|
||||
#if USE_SIMD
|
||||
public typealias Matrix3x3 = simd_float3x3
|
||||
public extension Matrix3x3
|
||||
{
|
||||
typealias T = Float
|
||||
}
|
||||
#else
|
||||
public struct Matrix3x3<T: FloatingPoint>: Equatable
|
||||
{
|
||||
public var m00: T, m01: T, m02: T
|
||||
public var m10: T, m11: T, m12: T
|
||||
public var m20: T, m21: T, m22: T
|
||||
|
||||
public init()
|
||||
{
|
||||
self.m00 = 1; self.m01 = 0; self.m02 = 0
|
||||
self.m10 = 0; self.m11 = 1; self.m12 = 0
|
||||
self.m20 = 0; self.m21 = 0; self.m22 = 1
|
||||
}
|
||||
|
||||
public init(
|
||||
_ a00: T, _ a01: T, _ a02: T,
|
||||
_ a10: T, _ a11: T, _ a12: T,
|
||||
_ a20: T, _ a21: T, _ a22: T)
|
||||
{
|
||||
self.m00 = a00; self.m01 = a01; self.m02 = a02
|
||||
self.m10 = a10; self.m11 = a11; self.m12 = a12
|
||||
self.m20 = a20; self.m21 = a21; self.m22 = a22
|
||||
}
|
||||
}
|
||||
|
||||
public extension Matrix3x3
|
||||
{
|
||||
init(_ row0: Vector3<T>, _ row1: Vector3<T>, _ row2: Vector3<T>)
|
||||
{
|
||||
self.m00 = row0.x; self.m01 = row0.y; self.m02 = row0.z
|
||||
self.m10 = row1.x; self.m11 = row1.y; self.m12 = row1.z
|
||||
self.m20 = row2.x; self.m21 = row2.y; self.m22 = row2.z
|
||||
}
|
||||
|
||||
@inline(__always) var identity: Self
|
||||
{
|
||||
Self(
|
||||
1, 0, 0,
|
||||
0, 1, 0,
|
||||
0, 0, 1)
|
||||
}
|
||||
|
||||
@inline(__always) var transpose: Self
|
||||
{
|
||||
Self(
|
||||
m00, m10, m20,
|
||||
m01, m11, m21,
|
||||
m02, m12, m22)
|
||||
}
|
||||
|
||||
static func * (lhs: Self, rhs: Self) -> Self
|
||||
{
|
||||
Self(
|
||||
lhs.m00 * rhs.m00 + lhs.m01 * rhs.m10 + lhs.m02 * rhs.m20,
|
||||
lhs.m00 * rhs.m01 + lhs.m01 * rhs.m11 + lhs.m02 * rhs.m21,
|
||||
lhs.m00 * rhs.m02 + lhs.m01 * rhs.m12 + lhs.m02 * rhs.m22,
|
||||
lhs.m10 * rhs.m00 + lhs.m11 * rhs.m10 + lhs.m12 * rhs.m20,
|
||||
lhs.m10 * rhs.m01 + lhs.m11 * rhs.m11 + lhs.m12 * rhs.m21,
|
||||
lhs.m10 * rhs.m02 + lhs.m11 * rhs.m12 + lhs.m12 * rhs.m22,
|
||||
lhs.m20 * rhs.m00 + lhs.m21 * rhs.m10 + lhs.m22 * rhs.m20,
|
||||
lhs.m20 * rhs.m01 + lhs.m21 * rhs.m11 + lhs.m22 * rhs.m21,
|
||||
lhs.m20 * rhs.m02 + lhs.m21 * rhs.m12 + lhs.m22 * rhs.m22)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public extension Matrix3x3
|
||||
{
|
||||
@inline(__always) static func lookAt(from: Vector3<T> = .zero, to: Vector3<T>, up: Vector3<T> = .up) -> Self
|
||||
{
|
||||
let direction = (to - from).normalised
|
||||
let normal = -direction
|
||||
let bitangent = up.cross(normal).normalised
|
||||
let tangent = normal.cross(bitangent).normalised
|
||||
|
||||
return Self(
|
||||
.init(bitangent.x, tangent.x, normal.x),
|
||||
.init(bitangent.y, tangent.y, normal.y),
|
||||
.init(bitangent.z, tangent.z, normal.z))
|
||||
}
|
||||
}
|
||||
|
||||
#if USE_SIMD
|
||||
public typealias Mat3f = Matrix3x3
|
||||
#else
|
||||
public typealias Mat3f = Matrix3x3<Float>
|
||||
public typealias Mat3d = Matrix3x3<Double>
|
||||
#endif
|
543
Sources/Maths/Matrix4x4.swift
Normal file
543
Sources/Maths/Matrix4x4.swift
Normal file
@ -0,0 +1,543 @@
|
||||
#if USE_SIMD
|
||||
import simd
|
||||
#endif
|
||||
|
||||
|
||||
#if USE_SIMD
|
||||
|
||||
public typealias Matrix4x4 = simd_float4x4
|
||||
public extension Matrix4x4
|
||||
{
|
||||
typealias T = Float
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
public struct Matrix4x4<T: FloatingPoint>: Equatable
|
||||
{
|
||||
public typealias Scalar = T
|
||||
|
||||
public var m00: T, m01: T, m02: T, m03: T
|
||||
public var m10: T, m11: T, m12: T, m13: T
|
||||
public var m20: T, m21: T, m22: T, m23: T
|
||||
public var m30: T, m31: T, m32: T, m33: T
|
||||
|
||||
public init()
|
||||
{
|
||||
self.m00 = 1; self.m01 = 0; self.m02 = 0; self.m03 = 0
|
||||
self.m10 = 0; self.m11 = 1; self.m12 = 0; self.m13 = 0
|
||||
self.m20 = 0; self.m21 = 0; self.m22 = 1; self.m23 = 0
|
||||
self.m30 = 0; self.m31 = 0; self.m32 = 0; self.m33 = 1
|
||||
}
|
||||
|
||||
public init(
|
||||
_ a00: T, _ a01: T, _ a02: T, _ a03: T,
|
||||
_ a10: T, _ a11: T, _ a12: T, _ a13: T,
|
||||
_ a20: T, _ a21: T, _ a22: T, _ a23: T,
|
||||
_ a30: T, _ a31: T, _ a32: T, _ a33: T)
|
||||
{
|
||||
self.m00 = a00; self.m01 = a01; self.m02 = a02; self.m03 = a03
|
||||
self.m10 = a10; self.m11 = a11; self.m12 = a12; self.m13 = a13
|
||||
self.m20 = a20; self.m21 = a21; self.m22 = a22; self.m23 = a23
|
||||
self.m30 = a30; self.m31 = a31; self.m32 = a32; self.m33 = a33
|
||||
}
|
||||
}
|
||||
|
||||
public extension Matrix4x4
|
||||
{
|
||||
init(diagonal d: Vector4<T>)
|
||||
{
|
||||
self.m00 = d.x; self.m01 = 0; self.m02 = 0; self.m03 = 0
|
||||
self.m10 = 0; self.m11 = d.y; self.m12 = 0; self.m13 = 0
|
||||
self.m20 = 0; self.m21 = 0; self.m22 = d.z; self.m23 = 0
|
||||
self.m30 = 0; self.m31 = 0; self.m32 = 0; self.m33 = d.w
|
||||
|
||||
}
|
||||
|
||||
init(_ row0: Vector4<T>, _ row1: Vector4<T>, _ row2: Vector4<T>, _ row3: Vector4<T>)
|
||||
{
|
||||
self.m00 = row0.x; self.m01 = row0.y; self.m02 = row0.z; self.m03 = row0.w
|
||||
self.m10 = row1.x; self.m11 = row1.y; self.m12 = row1.z; self.m13 = row1.w
|
||||
self.m20 = row2.x; self.m21 = row2.y; self.m22 = row2.z; self.m23 = row2.w
|
||||
self.m30 = row3.x; self.m31 = row3.y; self.m32 = row3.z; self.m33 = row3.w
|
||||
}
|
||||
|
||||
/*
|
||||
init(_ col0: Vector4<T>, _ col1: Vector4<T>, _ col2: Vector4<T>, _ col3: Vector4<T>)
|
||||
{
|
||||
self.m00 = col0.x; self.m01 = col1.x; self.m02 = col2.x; self.m03 = col3.x
|
||||
self.m10 = col0.y; self.m11 = col1.y; self.m12 = col2.y; self.m13 = col3.y
|
||||
self.m20 = col0.z; self.m21 = col1.z; self.m22 = col2.z; self.m23 = col3.z
|
||||
self.m30 = col0.w; self.m31 = col1.w; self.m32 = col2.w; self.m33 = col3.w
|
||||
}
|
||||
*/
|
||||
|
||||
subscript(index: Int) -> Vector4<T>
|
||||
{
|
||||
get
|
||||
{
|
||||
switch index
|
||||
{
|
||||
case 0: rows.0
|
||||
case 1: rows.1
|
||||
case 2: rows.2
|
||||
case 3: rows.3
|
||||
default: fatalError()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var rows: (Vector4<T>, Vector4<T>, Vector4<T>, Vector4<T>)
|
||||
{(
|
||||
.init(m00, m01, m02, m03),
|
||||
.init(m10, m11, m12, m13),
|
||||
.init(m20, m21, m22, m23),
|
||||
.init(m30, m31, m32, m33))
|
||||
}
|
||||
|
||||
var columns: (Vector4<T>, Vector4<T>, Vector4<T>, Vector4<T>)
|
||||
{(
|
||||
.init(m00, m10, m20, m30),
|
||||
.init(m01, m11, m21, m31),
|
||||
.init(m02, m12, m22, m32),
|
||||
.init(m03, m13, m23, m33))
|
||||
}
|
||||
|
||||
var transpose: Self
|
||||
{
|
||||
Self(
|
||||
m00, m10, m20, m30,
|
||||
m01, m11, m21, m31,
|
||||
m02, m12, m22, m32,
|
||||
m03, m13, m23, m33)
|
||||
}
|
||||
|
||||
static func * (lhs: Self, rhs: Self) -> Self
|
||||
{
|
||||
let l = rhs, r = lhs
|
||||
return Self(
|
||||
l.m00 * r.m00 + l.m01 * r.m10 + l.m02 * r.m20 + l.m03 * r.m30,
|
||||
l.m00 * r.m01 + l.m01 * r.m11 + l.m02 * r.m21 + l.m03 * r.m31,
|
||||
l.m00 * r.m02 + l.m01 * r.m12 + l.m02 * r.m22 + l.m03 * r.m32,
|
||||
l.m00 * r.m03 + l.m01 * r.m13 + l.m02 * r.m23 + l.m03 * r.m33,
|
||||
l.m10 * r.m00 + l.m11 * r.m10 + l.m12 * r.m20 + l.m13 * r.m30,
|
||||
l.m10 * r.m01 + l.m11 * r.m11 + l.m12 * r.m21 + l.m13 * r.m31,
|
||||
l.m10 * r.m02 + l.m11 * r.m12 + l.m12 * r.m22 + l.m13 * r.m32,
|
||||
l.m10 * r.m03 + l.m11 * r.m13 + l.m12 * r.m23 + l.m13 * r.m33,
|
||||
l.m20 * r.m00 + l.m21 * r.m10 + l.m22 * r.m20 + l.m23 * r.m30,
|
||||
l.m20 * r.m01 + l.m21 * r.m11 + l.m22 * r.m21 + l.m23 * r.m31,
|
||||
l.m20 * r.m02 + l.m21 * r.m12 + l.m22 * r.m22 + l.m23 * r.m32,
|
||||
l.m20 * r.m03 + l.m21 * r.m13 + l.m22 * r.m23 + l.m23 * r.m33,
|
||||
l.m30 * r.m00 + l.m31 * r.m10 + l.m32 * r.m20 + l.m33 * r.m30,
|
||||
l.m30 * r.m01 + l.m31 * r.m11 + l.m32 * r.m21 + l.m33 * r.m31,
|
||||
l.m30 * r.m02 + l.m31 * r.m12 + l.m32 * r.m22 + l.m33 * r.m32,
|
||||
l.m30 * r.m03 + l.m31 * r.m13 + l.m32 * r.m23 + l.m33 * r.m33)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if USE_SIMD
|
||||
|
||||
public extension Matrix4x4
|
||||
{
|
||||
init(quat q: Quaternion<T>)
|
||||
{
|
||||
self = .init(simd_quatf(ix: q.x, iy: q.y, iz: q.z, r: q.w)).transpose
|
||||
/*
|
||||
let FUCK = simd_matrix4x4(simd_quatf(ix: q.x, iy: q.y, iz: q.z, r: q.w))
|
||||
self = .init(
|
||||
FUCK.columns.0.x, FUCK.columns.1.x, FUCK.columns.2.x, FUCK.columns.3.x,
|
||||
FUCK.columns.0.y, FUCK.columns.1.y, FUCK.columns.2.y, FUCK.columns.3.y,
|
||||
FUCK.columns.0.z, FUCK.columns.1.z, FUCK.columns.2.z, FUCK.columns.3.z,
|
||||
FUCK.columns.0.w, FUCK.columns.1.w, FUCK.columns.2.w, FUCK.columns.3.w).transpose
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
public extension Matrix4x4 where T == Float
|
||||
{
|
||||
init(_ m3: Matrix3x3<T>)
|
||||
{
|
||||
self.m00 = m3.m00; self.m01 = m3.m01; self.m02 = m3.m02; self.m03 = 0
|
||||
self.m10 = m3.m10; self.m11 = m3.m11; self.m12 = m3.m12; self.m13 = 0
|
||||
self.m20 = m3.m20; self.m21 = m3.m21; self.m22 = m3.m22; self.m23 = 0
|
||||
self.m30 = 0; self.m31 = 0; self.m32 = 0; self.m33 = 1
|
||||
}
|
||||
|
||||
init(quat q: Quaternion<T>)
|
||||
{
|
||||
/*
|
||||
let qq = Quaternion<T>(q.w * q.w, q.x * q.x, q.y * q.y, q.z * q.z)
|
||||
return .init(
|
||||
.init(
|
||||
qq.w + qq.x - qq.y - qq.z,
|
||||
2.0 * (q.x * q.y - q.w * q.z),
|
||||
2.0 * (q.x * q.z + q.w * q.y),
|
||||
0.0),
|
||||
.init(
|
||||
2.0 * (q.x * q.y + q.w * q.z),
|
||||
qq.w - qq.x + qq.y - qq.z,
|
||||
2.0 * (q.y * q.z - q.w * q.x),
|
||||
0.0),
|
||||
.init(
|
||||
2.0 * (q.x * q.z - q.w * q.y),
|
||||
2.0 * (q.y * q.z + q.w * q.x),
|
||||
qq.w - qq.x - qq.y + qq.z,
|
||||
0.0),
|
||||
.init(0.0, 0.0, 0.0, 1.0))
|
||||
*/
|
||||
/*
|
||||
let qww = q.w * q.w
|
||||
let qxx = q.x * q.x
|
||||
let qyy = q.y * q.y
|
||||
let qzz = q.z * q.z
|
||||
.init(
|
||||
.init(
|
||||
qqw + qqx - qqy - qqz,
|
||||
2.0 * (q.x * q.y - q.w * q.z),
|
||||
2.0 * (q.x * q.z + q.w * q.y),
|
||||
0.0),
|
||||
.init(
|
||||
2.0 * (q.x * q.y + q.w * q.z),
|
||||
qqw - qqx + qqy - qqz,
|
||||
2.0 * (q.y * q.z - q.w * q.x),
|
||||
0.0),
|
||||
.init(
|
||||
2.0 * (q.x * q.z - q.w * q.y),
|
||||
2.0 * (q.y * q.z + q.w * q.x),
|
||||
qqw - qqx - qqy + qqz,
|
||||
0.0),
|
||||
.init(0.0, 0.0, 0.0, 1.0))
|
||||
*/
|
||||
let qww = q.w * q.w, qxx = q.x * q.x, qyy = q.y * q.y, qzz = q.z * q.z
|
||||
let qxy = q.x * q.y, qxz = q.x * q.z, qyz = q.y * q.z
|
||||
let qwx = q.w * q.x, qwy = q.w * q.y, qwz = q.w * q.z
|
||||
self = .init(
|
||||
.init(qww + qxx - qyy - qzz, 2 * (qxy - qwz), 2 * (qxz + qwy), 0),
|
||||
.init( 2 * (qxy + qwz), qww - qxx + qyy - qzz, 2 * (qyz - qwx), 0),
|
||||
.init( 2 * (qxz - qwy), 2 * (qyz + qwx), qww - qxx - qyy + qzz, 0),
|
||||
.init( 0, 0, 0, 1)).transpose
|
||||
}
|
||||
|
||||
@inline(__always) static var identity: Self { Self(diagonal: .one) }
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
public extension Matrix4x4
|
||||
{
|
||||
// what the fuck lmao
|
||||
@inline(__always) static func * (lhs: Self, rhs: Vector3<T>) -> Vector3<T>
|
||||
{
|
||||
return .init(
|
||||
lhs.columns.0.x * rhs.x + lhs.columns.0.y * rhs.y + lhs.columns.0.z * rhs.z,
|
||||
lhs.columns.1.x * rhs.x + lhs.columns.1.y * rhs.y + lhs.columns.1.z * rhs.z,
|
||||
lhs.columns.2.x * rhs.x + lhs.columns.2.y * rhs.y + lhs.columns.2.z * rhs.z)
|
||||
}
|
||||
}
|
||||
|
||||
#if USE_SIMD
|
||||
|
||||
public extension Matrix4x4
|
||||
{
|
||||
@inline(__always) static func translate(_ v: Vector3<T>) -> Self
|
||||
{
|
||||
Self(
|
||||
.init( 1, 0, 0, 0),
|
||||
.init( 0, 1, 0, 0),
|
||||
.init( 0, 0, 1, 0),
|
||||
.init(v.x, v.y, v.z, 1))
|
||||
}
|
||||
|
||||
@inline(__always) static func scale(_ v: Vector3<T>) -> Self
|
||||
{
|
||||
Self(
|
||||
.init(v.x, 0, 0, 0),
|
||||
.init( 0, v.y, 0, 0),
|
||||
.init( 0, 0, v.z, 0),
|
||||
.init( 0, 0, 0, 1))
|
||||
}
|
||||
|
||||
@inline(__always) static func scale(scalar v: T) -> Self
|
||||
{
|
||||
Self(
|
||||
.init(v, 0, 0, 0),
|
||||
.init(0, v, 0, 0),
|
||||
.init(0, 0, v, 0),
|
||||
.init(0, 0, 0, 1))
|
||||
}
|
||||
|
||||
@inline(__always) static func rotate(yawPitch: Vector2<T>) -> Self { return rotate(yaw: yawPitch.x, pitch: yawPitch.y) }
|
||||
|
||||
static func rotate(yaw ytheta: T, pitch xtheta: T) -> Self
|
||||
{
|
||||
let xc = xtheta.cosine, xs = xtheta.sine
|
||||
let yc = ytheta.cosine, ys = ytheta.sine
|
||||
|
||||
return Self(
|
||||
.init(yc, ys * xs, -ys * xc, 0),
|
||||
.init( 0, xc, xs, 0),
|
||||
.init(ys, yc * -xs, yc * xc, 0),
|
||||
.init( 0, 0, 0, 1))
|
||||
}
|
||||
|
||||
@inline(__always) static func rotate(x theta: T) -> Self
|
||||
{
|
||||
let c = theta.cosine, s = theta.sine
|
||||
return Self(
|
||||
.init(1, 0, 0, 0),
|
||||
.init(0, c, s, 0),
|
||||
.init(0, -s, c, 0),
|
||||
.init(0, 0, 0, 1))
|
||||
}
|
||||
|
||||
@inline(__always) static func rotate(y theta: T) -> Self
|
||||
{
|
||||
let c = theta.cosine, s = theta.sine
|
||||
return Self(
|
||||
.init(c, 0, -s, 0),
|
||||
.init(0, 1, 0, 0),
|
||||
.init(s, 0, c, 0),
|
||||
.init(0, 0, 0, 1))
|
||||
}
|
||||
|
||||
@inline(__always) static func rotate(z theta: T) -> Self
|
||||
{
|
||||
let c = theta.cosine, s = theta.sine
|
||||
return Self(
|
||||
.init(c, -s, 0, 0),
|
||||
.init(s, c, 0, 0),
|
||||
.init(0, 0, 1, 0),
|
||||
.init(0, 0, 0, 1))
|
||||
}
|
||||
|
||||
static func perspective(fovY: T, aspect: T, zNear: T, zFar: T) -> Self
|
||||
{
|
||||
let h = 1 / (fovY * T(0.5)).tangent
|
||||
let w = h / aspect
|
||||
let invClipRange = 1 / (zFar - zNear)
|
||||
let z = -(zFar + zNear) * invClipRange
|
||||
let z2 = -(2 * zFar * zNear) * invClipRange
|
||||
return Self(
|
||||
.init(w, 0, 0, 0),
|
||||
.init(0, h, 0, 0),
|
||||
.init(0, 0, z, -1),
|
||||
.init(0, 0, z2, 0))
|
||||
}
|
||||
|
||||
static func lookAt(from: Vector3<T> = .zero, to: Vector3<T>, up: Vector3<T> = .up) -> Self
|
||||
{
|
||||
let forward = (to - from).normalised
|
||||
let bitangent = forward.cross(up).normalised
|
||||
let tangent = bitangent.cross(forward).normalised
|
||||
let normal = -forward
|
||||
|
||||
return Self(
|
||||
.init(bitangent, 0),
|
||||
.init( tangent, 0),
|
||||
.init( normal, 0),
|
||||
.init(0, 0, 0, 1))
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
public extension Matrix4x4 where T == Float
|
||||
{
|
||||
@inline(__always) static func translate(_ v: Vector3<T>) -> Self
|
||||
{
|
||||
Self(
|
||||
.init( 1, 0, 0, 0),
|
||||
.init( 0, 1, 0, 0),
|
||||
.init( 0, 0, 1, 0),
|
||||
.init(v.x, v.y, v.z, 1))
|
||||
}
|
||||
|
||||
@inline(__always) static func scale(_ v: Vector3<T>) -> Self
|
||||
{
|
||||
Self(
|
||||
.init(v.x, 0, 0, 0),
|
||||
.init( 0, v.y, 0, 0),
|
||||
.init( 0, 0, v.z, 0),
|
||||
.init( 0, 0, 0, 1))
|
||||
}
|
||||
|
||||
@inline(__always) static func scale(scalar v: T) -> Self
|
||||
{
|
||||
Self(
|
||||
.init(v, 0, 0, 0),
|
||||
.init(0, v, 0, 0),
|
||||
.init(0, 0, v, 0),
|
||||
.init(0, 0, 0, 1))
|
||||
}
|
||||
|
||||
static func rotate(axis v: Vector3<T>, angle theta: T) -> Self
|
||||
{
|
||||
//FIXME: THIS IS FUCKED UP FOR EVERYTHING OTHER THAN X AXIS ROTATION LOL
|
||||
/*
|
||||
let vv = v * v
|
||||
let xy = v.x * v.y, xz = v.x * v.z, yz = v.y * v.z
|
||||
let ts = sin(theta), tc = cos(theta)
|
||||
return Self(
|
||||
.init(
|
||||
vv.x + (tc * (1 - vv.x)),
|
||||
(xz - (tc * xy)) + (ts * v.z),
|
||||
(xz - (tc * xz)) - (ts * v.y), 0),
|
||||
.init(
|
||||
(xy - (tc * xy)) - (ts * v.z),
|
||||
vv.y + (tc * (1 - vv.y)),
|
||||
(xz - (tc * xz)) + (ts * v.x), 0),
|
||||
.init(
|
||||
(xz - (tc * xz)) + (ts * v.y),
|
||||
(xz - (tc * xz)) - (ts * v.y),
|
||||
vv.z + (tc * (1 - vv.z)), 1),
|
||||
.init(0, 0, 0, 1))
|
||||
*/
|
||||
let vxx = v.x * v.x, vxy = v.x * v.y, vxz = v.x * v.z
|
||||
let vyy = v.y * v.y, vyz = v.y * v.z
|
||||
let vzz = v.z * v.z
|
||||
let ts = theta.sine, tc = theta.cosine
|
||||
let ic = 1 - tc
|
||||
return Self(
|
||||
.init(
|
||||
ic * vxx + tc,
|
||||
ic * vxy - v.z * ts,
|
||||
ic * vxz + v.z * ts,
|
||||
0),
|
||||
.init(
|
||||
ic * vxy + v.z * ts,
|
||||
ic * vyy + tc,
|
||||
ic * vyz - v.x * ts,
|
||||
0),
|
||||
.init(
|
||||
ic * vxz - v.y * ts,
|
||||
ic * vyz + v.x * ts,
|
||||
ic * vzz + tc,
|
||||
0),
|
||||
.init(0, 0, 0, 1))
|
||||
}
|
||||
|
||||
@inline(__always) static func rotate(yawPitch: Vector2<T>) -> Self { return rotate(yaw: yawPitch.x, pitch: yawPitch.y) }
|
||||
|
||||
static func rotate(yaw ytheta: T, pitch xtheta: T) -> Self
|
||||
{
|
||||
let xc = xtheta.cosine, xs = xtheta.sine
|
||||
let yc = ytheta.cosine, ys = ytheta.sine
|
||||
|
||||
return Self(
|
||||
.init(yc, ys * xs, -ys * xc, 0),
|
||||
.init( 0, xc, xs, 0),
|
||||
.init(ys, yc * -xs, yc * xc, 0),
|
||||
.init( 0, 0, 0, 1))
|
||||
}
|
||||
|
||||
static func rotate(yaw ytheta: T, pitch xtheta: T, roll ztheta: T) -> Self
|
||||
{
|
||||
//FIXME: this doesn't null against control
|
||||
let xc = xtheta.cosine, xs = xtheta.sine
|
||||
let yc = ytheta.cosine, ys = ytheta.sine
|
||||
let zc = ztheta.cosine, zs = ztheta.sine
|
||||
|
||||
let ysxs = ys * xs, ycxs = yc * xs
|
||||
|
||||
let result = Mat4f(
|
||||
.init(yc * zc + ysxs * zs, yc * -zs + ysxs * zc, -ys * xc, 0),
|
||||
.init( xc * zs, xc * zc, xs, 0),
|
||||
.init(ys * zc - ycxs * zs, ys * -zs - ycxs * zc, yc * xc, 0),
|
||||
.init( 0, 0, 0, 1))
|
||||
let shouldBe = .rotate(z: ztheta) * .rotate(x: xtheta) * .rotate(y: ytheta)
|
||||
|
||||
let epsilon: Float = .ulpOfOne
|
||||
if (result != shouldBe)
|
||||
{
|
||||
assert(abs(result[0][0] - shouldBe[0][0]) <= epsilon) // epsilon
|
||||
assert(result[1][0] == shouldBe[1][0])
|
||||
assert(abs(result[2][0] - shouldBe[2][0]) <= epsilon) // epsilon
|
||||
assert(result[3][0] == shouldBe[3][0])
|
||||
assert(abs(result[0][1] - shouldBe[0][1]) <= epsilon) // epsilon
|
||||
assert(result[1][1] == shouldBe[1][1])
|
||||
assert(abs(result[2][1] - shouldBe[2][1]) <= epsilon) // epsilon
|
||||
assert(result[3][1] == shouldBe[3][1])
|
||||
assert(result[0][2] == shouldBe[0][2])
|
||||
assert(result[1][2] == shouldBe[1][2])
|
||||
assert(result[2][2] == shouldBe[2][2])
|
||||
assert(result[3][2] == shouldBe[3][2])
|
||||
assert(result[0][3] == shouldBe[0][3])
|
||||
assert(result[1][3] == shouldBe[1][3])
|
||||
assert(result[2][3] == shouldBe[2][3])
|
||||
assert(result[3][3] == shouldBe[3][3])
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@inline(__always) static func rotate(x theta: T) -> Self
|
||||
{
|
||||
let c = theta.cosine, s = theta.sine
|
||||
return Self(
|
||||
.init(1, 0, 0, 0),
|
||||
.init(0, c, s, 0),
|
||||
.init(0, -s, c, 0),
|
||||
.init(0, 0, 0, 1))
|
||||
}
|
||||
|
||||
@inline(__always) static func rotate(y theta: T) -> Self
|
||||
{
|
||||
let c = theta.cosine, s = theta.sine
|
||||
return Self(
|
||||
.init(c, 0, -s, 0),
|
||||
.init(0, 1, 0, 0),
|
||||
.init(s, 0, c, 0),
|
||||
.init(0, 0, 0, 1))
|
||||
}
|
||||
|
||||
@inline(__always) static func rotate(z theta: T) -> Self
|
||||
{
|
||||
let c = theta.cosine, s = theta.sine
|
||||
return Self(
|
||||
.init(c, -s, 0, 0),
|
||||
.init(s, c, 0, 0),
|
||||
.init(0, 0, 1, 0),
|
||||
.init(0, 0, 0, 1))
|
||||
}
|
||||
|
||||
static func perspective(fovY: T, aspect: T, zNear: T, zFar: T) -> Self
|
||||
{
|
||||
let h = 1 / (fovY * 0.5).tangent
|
||||
let w = h / aspect
|
||||
let invClipRange = 1 / (zFar - zNear)
|
||||
let z = -(zFar + zNear) * invClipRange
|
||||
let z2 = -(2 * zFar * zNear) * invClipRange
|
||||
return Self(
|
||||
.init(w, 0, 0, 0),
|
||||
.init(0, h, 0, 0),
|
||||
.init(0, 0, z, -1),
|
||||
.init(0, 0, z2, 0))
|
||||
}
|
||||
|
||||
static func lookAt(from: Vector3<T> = .zero, to: Vector3<T>, up: Vector3<T> = .up) -> Self
|
||||
{
|
||||
let forward = (to - from).normalised
|
||||
let bitangent = forward.cross(up).normalised
|
||||
let tangent = bitangent.cross(forward).normalised
|
||||
let normal = -forward
|
||||
|
||||
return Self(
|
||||
.init(bitangent, 0),
|
||||
.init( tangent, 0),
|
||||
.init( normal, 0),
|
||||
.init(0, 0, 0, 1))
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if USE_SIMD
|
||||
public typealias Mat4f = Matrix4x4
|
||||
#else
|
||||
public typealias Mat4f = Matrix4x4<Float>
|
||||
public typealias Mat4d = Matrix4x4<Double>
|
||||
#endif
|
333
Sources/Maths/Quaternion.swift
Normal file
333
Sources/Maths/Quaternion.swift
Normal file
@ -0,0 +1,333 @@
|
||||
import Foundation
|
||||
import simd
|
||||
|
||||
|
||||
public struct Quaternion<T: FloatingPoint>: Equatable
|
||||
{
|
||||
public var w: T, x: T, y: T, z: T
|
||||
|
||||
public init() { self.x = 0; self.y = 0; self.z = 0; self.w = 1 }
|
||||
public init(_ w: T, _ x: T, _ y: T, _ z: T) { self.w = w; self.x = x; self.y = y; self.z = z }
|
||||
|
||||
public static var identity: Self { .init(1, 0, 0, 0) }
|
||||
}
|
||||
|
||||
public extension Quaternion where T: SIMDScalar
|
||||
{
|
||||
init(real w: T, imaginary i: Vector3<T>) { self.w = w; self.x = i.x; self.y = i.y; self.z = i.z }
|
||||
}
|
||||
|
||||
#if USE_SIMD
|
||||
|
||||
public extension Quaternion where T == Float
|
||||
{
|
||||
init(_ q: simd_quatf)
|
||||
{
|
||||
self.init(real: q.real, imaginary: q.imag)
|
||||
}
|
||||
|
||||
static func lookAt(from: Vector3<T> = .zero, to: Vector3<T>, up: Vector3<T> = .up) -> Self
|
||||
{
|
||||
let m3 = Matrix3x3.lookAt(from: from, to: to, up: up)
|
||||
let et_blee_eve_nyu = simd_quatf(m3)
|
||||
return Self(real: et_blee_eve_nyu.real, imaginary: .init(
|
||||
et_blee_eve_nyu.imag.x,
|
||||
et_blee_eve_nyu.imag.y,
|
||||
et_blee_eve_nyu.imag.z))
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
public extension Quaternion where T == Float
|
||||
{
|
||||
init(_ m3: Matrix3x3<T>)
|
||||
{
|
||||
if m3.m22 < 0
|
||||
{
|
||||
if m3.m00 > m3.m11
|
||||
{
|
||||
let t = 1 + m3.m00 - m3.m11 - m3.m22
|
||||
self.x = t.squareRoot() * 0.5
|
||||
if m3.m21 < m3.m12 { self.x = -self.x }
|
||||
let ix4 = 1 / (4 * self.x)
|
||||
self.w = (m3.m21 - m3.m12) * ix4
|
||||
self.y = (m3.m10 + m3.m01) * ix4
|
||||
self.z = (m3.m02 + m3.m20) * ix4
|
||||
if t == 1 && self.w == 0 && self.y == 0 && self.z == 0 { self.x = 1 }
|
||||
}
|
||||
else
|
||||
{
|
||||
let t = 1 - m3.m00 + m3.m11 - m3.m22
|
||||
self.y = t.squareRoot() * 0.5
|
||||
if m3.m02 < m3.m20 { self.y = -self.y }
|
||||
let iy4 = 1 / (4 * self.y)
|
||||
self.w = (m3.m02 - m3.m20) * iy4
|
||||
self.x = (m3.m10 + m3.m01) * iy4
|
||||
self.z = (m3.m21 + m3.m12) * iy4
|
||||
if t == 1 && self.w == 0 && self.x == 0 && self.z == 0 { self.y = 1 }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if m3.m00 < -m3.m11
|
||||
{
|
||||
let t = 1 - m3.m00 - m3.m11 + m3.m22
|
||||
self.z = t.squareRoot() * 0.5
|
||||
if m3.m10 < m3.m01 { self.z = -self.z }
|
||||
let iz4 = 1 / (4 * self.z)
|
||||
self.w = (m3.m10 - m3.m01) * iz4
|
||||
self.x = (m3.m02 + m3.m20) * iz4
|
||||
self.y = (m3.m21 + m3.m12) * iz4
|
||||
if t == 1 && self.w == 0 && self.x == 0 && self.y == 0 { self.z = 1 }
|
||||
}
|
||||
else
|
||||
{
|
||||
let t = 1 + m3.m00 + m3.m11 + m3.m22
|
||||
self.w = t.squareRoot() * 0.5
|
||||
let iw4 = 1 / (4 * self.w)
|
||||
self.x = (m3.m21 - m3.m12) * iw4
|
||||
self.y = (m3.m02 - m3.m20) * iw4
|
||||
self.z = (m3.m10 - m3.m01) * iw4
|
||||
if t == 1 && self.x == 0 && self.y == 0 && self.z == 0 { self.w = 1 }
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
let m3 = m3FUCK.transpose
|
||||
if m3.m22 < 0
|
||||
{
|
||||
if m3.m00 > m3.m11
|
||||
{
|
||||
let t = 1 + m3.m00 - m3.m11 - m3.m22
|
||||
self.x = t.squareRoot() * 0.5
|
||||
if m3.m12 < m3.m21 { self.x = -self.x }
|
||||
let ix4 = 1 / (4 * self.x)
|
||||
self.w = (m3.m12 - m3.m21) * ix4
|
||||
self.y = (m3.m01 + m3.m10) * ix4
|
||||
self.z = (m3.m20 + m3.m02) * ix4
|
||||
if t == 1 && self.w == 0 && self.y == 0 && self.z == 0 { self.x = 1 }
|
||||
}
|
||||
else
|
||||
{
|
||||
let t = 1 - m3.m00 + m3.m11 - m3.m22
|
||||
self.y = t.squareRoot() * 0.5
|
||||
if m3.m20 < m3.m02 { self.y = -self.y }
|
||||
let iy4 = 1 / (4 * self.y)
|
||||
self.w = (m3.m20 - m3.m02) * iy4
|
||||
self.x = (m3.m01 + m3.m10) * iy4
|
||||
self.z = (m3.m12 + m3.m21) * iy4
|
||||
if t == 1 && self.w == 0 && self.x == 0 && self.z == 0 { self.y = 1 }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if m3.m00 < -m3.m11
|
||||
{
|
||||
let t = 1 - m3.m00 - m3.m11 + m3.m22
|
||||
self.z = t.squareRoot() * 0.5
|
||||
if m3.m01 < m3.m10 { self.z = -self.z }
|
||||
let iz4 = 1 / (4 * self.z)
|
||||
self.w = (m3.m01 - m3.m10) * iz4
|
||||
self.x = (m3.m20 + m3.m02) * iz4
|
||||
self.y = (m3.m12 + m3.m21) * iz4
|
||||
if t == 1 && self.w == 0 && self.x == 0 && self.y == 0 { self.z = 1 }
|
||||
}
|
||||
else
|
||||
{
|
||||
let t = 1 + m3.m00 + m3.m11 + m3.m22
|
||||
self.w = t.squareRoot() * 0.5
|
||||
let iw4 = 1 / (4 * self.w)
|
||||
self.x = (m3.m12 - m3.m21) * iw4
|
||||
self.y = (m3.m20 - m3.m02) * iw4
|
||||
self.z = (m3.m01 - m3.m10) * iw4
|
||||
if t == 1 && self.x == 0 && self.y == 0 && self.z == 0 { self.w = 1 }
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
self.w = (1 + m3.m00 + m3.m11 + m3.m22).squareRoot() * 0.5
|
||||
let iw4 = 1 / (4 * self.w)
|
||||
self.x = (m3.m21 - m3.m12) * iw4
|
||||
self.y = (m3.m02 - m3.m20) * iw4
|
||||
self.z = (m3.m10 - m3.m01) * iw4
|
||||
*/
|
||||
/*
|
||||
if m3.m22 < 0
|
||||
{
|
||||
if m3.m00 > m3.m11
|
||||
{
|
||||
self.w = (1 + m3.m00 - m3.m11 - m3.m22).squareRoot() * 0.5
|
||||
let iw4 = 1 / (4 * self.w)
|
||||
//self.x = (m3.m01 + m3.m10) * iw4
|
||||
//self.y = (m3.m20 + m3.m02) * iw4
|
||||
//self.z = (m3.m12 - m3.m21) * iw4
|
||||
self.x = (m3.m21 - m3.m12) * iw4
|
||||
self.y = (m3.m02 - m3.m20) * iw4
|
||||
self.z = (m3.m10 - m3.m01) * iw4
|
||||
}
|
||||
else
|
||||
{
|
||||
self.x = (1 - m3.m00 + m3.m11 - m3.m22).squareRoot() * 0.5
|
||||
let ix4 = 1 / (4 * self.x)
|
||||
//self.w = (m3.m01 + m3.m10) * ix4
|
||||
//self.y = (m3.m12 + m3.m21) * ix4
|
||||
//self.z = (m3.m20 - m3.m02) * ix4
|
||||
self.z = (m3.m02 - m3.m20) * ix4
|
||||
self.y = (m3.m21 - m3.m12) * ix4
|
||||
self.w = (m3.m10 - m3.m01) * ix4
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if m3.m00 < -m3.m11
|
||||
{
|
||||
self.y = (1 - m3.m00 - m3.m11 + m3.m22).squareRoot() * 0.5
|
||||
let iy4 = 1 / (4 * self.y)
|
||||
//self.w = (m3.m20 + m3.m02) * iy4
|
||||
//self.x = (m3.m12 + m3.m21) * iy4
|
||||
//self.z = (m3.m01 - m3.m10) * iy4
|
||||
self.z = (m3.m10 - m3.m01) * iy4
|
||||
self.x = (m3.m21 - m3.m12) * iy4
|
||||
self.w = (m3.m02 - m3.m20) * iy4
|
||||
}
|
||||
else
|
||||
{
|
||||
self.z = (1 + m3.m00 + m3.m11 + m3.m22).squareRoot() * 0.5
|
||||
let iz4 = 1 / (4 * self.z)
|
||||
//self.w = (m3.m12 - m3.m21) * iz4
|
||||
//self.x = (m3.m20 - m3.m02) * iz4
|
||||
//self.y = (m3.m01 - m3.m10) * iz4
|
||||
self.y = (m3.m10 - m3.m01) * iz4
|
||||
self.x = (m3.m02 - m3.m20) * iz4
|
||||
self.w = (m3.m21 - m3.m12) * iz4
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
static func lookAt(from: Vector3<T> = .zero, to: Vector3<T>, up: Vector3<T> = .up) -> Self
|
||||
{
|
||||
Self(Matrix3x3<T>.lookAt(from: from, to: to, up: up))
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
public extension Quaternion where T == Float
|
||||
{
|
||||
init(axis v: Vector3<T>, angle theta: T)
|
||||
{
|
||||
let tc = (theta * 0.5).cosine, ts = (theta * 0.5).sine
|
||||
self.init(real: tc, imaginary: v * ts)
|
||||
}
|
||||
|
||||
@inline(__always) func slerp(_ rhs: Self, _ theta: T) -> Self
|
||||
{
|
||||
var b = rhs
|
||||
var cosHalfTheta = self.dot(b)
|
||||
if abs(cosHalfTheta) >= 1
|
||||
{
|
||||
// if a == b or a == -b then theta == 0
|
||||
return self
|
||||
}
|
||||
else if cosHalfTheta < 0
|
||||
{
|
||||
b = -b
|
||||
cosHalfTheta = -cosHalfTheta
|
||||
}
|
||||
let halfTheta = acos(cosHalfTheta)
|
||||
let sinHalfTheta = (1 - cosHalfTheta * cosHalfTheta).squareRoot()
|
||||
if abs(sinHalfTheta) <= .ulpOfOne
|
||||
{
|
||||
// if theta == 180 degrees then result is not fully defined
|
||||
// we could rotate around any axis normal to a or b
|
||||
return (self + b) * 0.5
|
||||
}
|
||||
let ratioA = ((1 - theta) * halfTheta).sine / sinHalfTheta
|
||||
let ratioB = (theta * halfTheta).sine / sinHalfTheta
|
||||
return self * ratioA + b * ratioB
|
||||
//let piss = simd_quatf(ix: x, iy: y, iz: z, r: w)
|
||||
//let shit = simd_quatf(ix: b.x, iy: b.y, iz: b.z, r: b.w)
|
||||
//let cunt = simd_slerp(piss, shit, x)
|
||||
//return .init(real: cunt.real, imaginary: cunt.imag)
|
||||
}
|
||||
|
||||
// Because swift type checking brain injury
|
||||
@inline(__always) static func * (a: Self, b: Self) -> Self
|
||||
{
|
||||
.init(
|
||||
a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z,
|
||||
a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y,
|
||||
a.w * b.y - a.x * b.z + a.y * b.w + a.z * b.x,
|
||||
a.w * b.z + a.x * b.y - a.y * b.x + a.z * b.w)
|
||||
}
|
||||
}
|
||||
|
||||
public extension Quaternion where T: FloatingPoint
|
||||
{
|
||||
@inline(__always) static prefix func - (this: Self) -> Self
|
||||
{
|
||||
.init(-this.w, -this.x, -this.y, -this.z)
|
||||
}
|
||||
|
||||
@inline(__always) static func + (lhs: Self, rhs: Self) -> Self
|
||||
{
|
||||
.init(lhs.w + rhs.w, lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z)
|
||||
}
|
||||
|
||||
@inline(__always) static func * (lhs: Self, rhs: T) -> Self
|
||||
{
|
||||
.init(lhs.w * rhs, lhs.x * rhs, lhs.y * rhs, lhs.z * rhs)
|
||||
}
|
||||
|
||||
@inline(__always) mutating func normalise()
|
||||
{
|
||||
let invMag = 1 / self.dot(self).squareRoot()
|
||||
self.w *= invMag
|
||||
self.x *= invMag
|
||||
self.y *= invMag
|
||||
self.z *= invMag
|
||||
}
|
||||
|
||||
@inline(__always) var normalised: Self
|
||||
{
|
||||
let invMag = 1 / self.dot(self).squareRoot()
|
||||
return self * invMag
|
||||
}
|
||||
|
||||
@inline(__always) func dot(_ b: Self) -> T { x * b.x + y * b.y + z * b.z + w * b.w }
|
||||
}
|
||||
|
||||
|
||||
#if USE_SIMD
|
||||
|
||||
public extension Vector3 where Scalar == Float
|
||||
{
|
||||
@inline(__always) static func * (v: Self, q: Quaternion<Scalar>) -> Self
|
||||
{
|
||||
return v * simd_float3x3(simd_quatf(ix: q.x, iy: q.y, iz: q.z, r: q.w))
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
public extension Vector3 where T: BinaryFloatingPoint
|
||||
{
|
||||
@inline(__always) static func * (v: Self, q: Quaternion<T>) -> Self
|
||||
{
|
||||
let qw = q.w, qv = Self(q.x, q.y, q.z)
|
||||
|
||||
var out = qv * 2.0 * qv.dot(v)
|
||||
out += v * (qw * qw - qv.dot(qv))
|
||||
return out + qv.cross(v) * 2.0 * qw
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
public typealias Quatf = Quaternion<Float>
|
||||
public typealias Quatd = Quaternion<Double>
|
98
Sources/Maths/Vector2.swift
Normal file
98
Sources/Maths/Vector2.swift
Normal file
@ -0,0 +1,98 @@
|
||||
import Foundation
|
||||
#if USE_SIMD
|
||||
import simd
|
||||
#endif
|
||||
|
||||
|
||||
#if USE_SIMD
|
||||
public typealias Vector2 = SIMD2
|
||||
#else
|
||||
|
||||
public struct Vector2<T: FloatingPoint>: Equatable
|
||||
{
|
||||
public typealias Scalar = T
|
||||
|
||||
public var x, y: T
|
||||
|
||||
public init() { self.x = 0; self.y = 0 }
|
||||
public init(_ x: T, _ y: T) { self.x = x; self.y = y }
|
||||
}
|
||||
|
||||
public extension Vector2
|
||||
{
|
||||
// constants
|
||||
@inline(__always) static var zero: Self { Self(0, 0) }
|
||||
@inline(__always) static var one: Self { Self(1, 1) }
|
||||
|
||||
subscript(index: Int) -> T
|
||||
{
|
||||
get
|
||||
{
|
||||
switch index
|
||||
{
|
||||
case 0: x
|
||||
case 1: y
|
||||
default: fatalError()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// relational
|
||||
@inline(__always) static func == (lhs: Self, rhs: Self) -> Bool { lhs.x == rhs.x && lhs.y == rhs.y }
|
||||
@inline(__always) static func != (lhs: Self, rhs: Self) -> Bool { rhs.x != rhs.x || lhs.y != rhs.y }
|
||||
|
||||
// arithmetic
|
||||
@inline(__always) static func + (lhs: Self, rhs: Self) -> Self { Self(lhs.x + rhs.x, lhs.y + rhs.y) }
|
||||
@inline(__always) static func - (lhs: Self, rhs: Self) -> Self { Self(lhs.x - rhs.x, lhs.y - rhs.y) }
|
||||
@inline(__always) static func * (lhs: Self, rhs: Self) -> Self { Self(lhs.x * rhs.x, lhs.y * rhs.y) }
|
||||
@inline(__always) static func / (lhs: Self, rhs: Self) -> Self { Self(lhs.x / rhs.x, lhs.y / rhs.y) }
|
||||
|
||||
// scalar arithmetic
|
||||
@inline(__always) static func * (lhs: Self, rhs: T) -> Self { Self(lhs.x * rhs, lhs.y * rhs) }
|
||||
@inline(__always) static func / (lhs: Self, rhs: T) -> Self { Self(lhs.x / rhs, lhs.y / rhs) }
|
||||
@inline(__always) static func * (lhs: T, rhs: Self) -> Self { Self(lhs * rhs.x, lhs * rhs.y) }
|
||||
@inline(__always) static func / (lhs: T, rhs: Self) -> Self { Self(lhs / rhs.x, lhs / rhs.y) }
|
||||
|
||||
// compound arithmetic
|
||||
@inline(__always) static func += (lhs: inout Self, rhs: Self) { lhs.x += rhs.x; lhs.y += rhs.y }
|
||||
@inline(__always) static func -= (lhs: inout Self, rhs: Self) { lhs.x -= rhs.x; lhs.y -= rhs.y }
|
||||
@inline(__always) static func *= (lhs: inout Self, rhs: Self) { lhs.x *= rhs.x; lhs.y *= rhs.y }
|
||||
@inline(__always) static func /= (lhs: inout Self, rhs: Self) { lhs.x /= rhs.x; lhs.y /= rhs.y }
|
||||
|
||||
// compound scalar arithmetic
|
||||
@inline(__always) static func *= (lhs: inout Self, rhs: T) { lhs.x *= rhs; lhs.y *= rhs }
|
||||
@inline(__always) static func /= (lhs: inout Self, rhs: T) { lhs.x /= rhs; lhs.y /= rhs }
|
||||
|
||||
// unary
|
||||
@inline(__always) static prefix func + (vec: Self) -> Self { vec }
|
||||
@inline(__always) static prefix func - (vec: Self) -> Self { Self(-vec.x, -vec.y) }
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
public extension Vector2 where Scalar: FloatingPoint
|
||||
{
|
||||
@inline(__always) var len2: Scalar { x * x + y * y }
|
||||
@inline(__always) var len: Scalar { len2.squareRoot() }
|
||||
@inline(__always) var normalised: Self { let invLen = 1 / len; return self * invLen }
|
||||
|
||||
@inline(__always) mutating func normalise() { let invLen = 1 / len; self *= invLen }
|
||||
|
||||
@inline(__always) func dot(_ b: Self) -> Scalar { x * b.x + y * b.y }
|
||||
@inline(__always) func reflect(_ n: Self) -> Self { self - (n * 2 * self.dot(n)) }
|
||||
@inline(__always) func project(_ n: Self) -> Self { n * self.dot(n) }
|
||||
|
||||
@inline(__always) func cross(_ b: Self) -> Scalar { x * b.y - y * b.x }
|
||||
|
||||
@inline(__always) func lerp(_ b: Self, _ x: Scalar) -> Self
|
||||
{
|
||||
let invX = 1 - x
|
||||
return Self(self.x * invX + b.x * x, self.y * invX + b.y * x)
|
||||
}
|
||||
|
||||
@inline(__always) func distance(_ b: Self) -> Scalar { return (b - self).len }
|
||||
}
|
||||
|
||||
|
||||
public typealias Vec2f = Vector2<Float>
|
||||
public typealias Vec2d = Vector2<Double>
|
112
Sources/Maths/Vector3.swift
Normal file
112
Sources/Maths/Vector3.swift
Normal file
@ -0,0 +1,112 @@
|
||||
#if USE_SIMD
|
||||
import simd
|
||||
#endif
|
||||
|
||||
|
||||
#if USE_SIMD
|
||||
public typealias Vector3 = SIMD3
|
||||
public extension Vector3
|
||||
{
|
||||
typealias T = Scalar
|
||||
}
|
||||
#else
|
||||
|
||||
public struct Vector3<T: FloatingPoint>: Equatable
|
||||
{
|
||||
public typealias Scalar = T
|
||||
|
||||
public var x, y, z: T
|
||||
|
||||
public init() { self.x = 0; self.y = 0; self.z = 0 }
|
||||
public init(_ x: T, _ y: T, _ z: T) { self.x = x; self.y = y; self.z = z }
|
||||
}
|
||||
|
||||
public extension Vector3
|
||||
{
|
||||
// constants
|
||||
@inline(__always) static var zero: Self { Self(0, 0, 0) }
|
||||
@inline(__always) static var one: Self { Self(1, 1, 1) }
|
||||
|
||||
subscript(index: Int) -> T
|
||||
{
|
||||
get
|
||||
{
|
||||
switch index
|
||||
{
|
||||
case 0: x
|
||||
case 1: y
|
||||
case 2: z
|
||||
default: fatalError()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init(repeating v: T) { self.x = v; self.y = v; self.z = v }
|
||||
|
||||
// relational
|
||||
@inline(__always) static func == (lhs: Self, rhs: Self) -> Bool { lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z }
|
||||
@inline(__always) static func != (lhs: Self, rhs: Self) -> Bool { lhs.x != rhs.x || lhs.y != rhs.y || lhs.z != rhs.z }
|
||||
|
||||
// arithmetic
|
||||
@inline(__always) static func + (lhs: Self, rhs: Self) -> Self { Self(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z) }
|
||||
@inline(__always) static func - (lhs: Self, rhs: Self) -> Self { Self(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z) }
|
||||
@inline(__always) static func * (lhs: Self, rhs: Self) -> Self { Self(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z) }
|
||||
@inline(__always) static func / (lhs: Self, rhs: Self) -> Self { Self(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z) }
|
||||
|
||||
// scalar arithmetic
|
||||
@inline(__always) static func * (lhs: Self, rhs: T) -> Self { Self(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs) }
|
||||
@inline(__always) static func / (lhs: Self, rhs: T) -> Self { Self(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs) }
|
||||
@inline(__always) static func * (lhs: T, rhs: Self) -> Self { Self(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z) }
|
||||
@inline(__always) static func / (lhs: T, rhs: Self) -> Self { Self(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z) }
|
||||
|
||||
// compound arithmetic
|
||||
@inline(__always) static func += (lhs: inout Self, rhs: Self) { lhs.x += rhs.x; lhs.y += rhs.y; lhs.z += rhs.z }
|
||||
@inline(__always) static func -= (lhs: inout Self, rhs: Self) { lhs.x -= rhs.x; lhs.y -= rhs.y; lhs.z -= rhs.z }
|
||||
@inline(__always) static func *= (lhs: inout Self, rhs: Self) { lhs.x *= rhs.x; lhs.y *= rhs.y; lhs.z *= rhs.z }
|
||||
@inline(__always) static func /= (lhs: inout Self, rhs: Self) { lhs.x /= rhs.x; lhs.y /= rhs.y; lhs.z /= rhs.z }
|
||||
|
||||
// compound scalar arithmetic
|
||||
@inline(__always) static func *= (lhs: inout Self, rhs: T) { lhs.x *= rhs; lhs.y *= rhs; lhs.z *= rhs }
|
||||
@inline(__always) static func /= (lhs: inout Self, rhs: T) { lhs.x /= rhs; lhs.y /= rhs; lhs.z /= rhs }
|
||||
|
||||
// unary
|
||||
@inline(__always) static prefix func + (vec: Self) -> Self { vec }
|
||||
@inline(__always) static prefix func - (vec: Self) -> Self { Self(-vec.x, -vec.y, -vec.z) }
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
public extension Vector3 where Scalar: FloatingPoint
|
||||
{
|
||||
@inline(__always) static var X: Self { Self(1, 0, 0) }
|
||||
@inline(__always) static var Y: Self { Self(0, 1, 0) }
|
||||
@inline(__always) static var Z: Self { Self(0, 0, 1) }
|
||||
|
||||
@inline(__always) static var up: Self { Y }
|
||||
@inline(__always) static var down: Self { -Y }
|
||||
@inline(__always) static var left: Self { -X }
|
||||
@inline(__always) static var right: Self { X }
|
||||
@inline(__always) static var forward: Self { -Z }
|
||||
@inline(__always) static var back: Self { Z }
|
||||
|
||||
@inline(__always) var len2: Scalar { x * x + y * y + z * z }
|
||||
@inline(__always) var len: Scalar { len2.squareRoot() }
|
||||
@inline(__always) var normalised: Self { let invLen = 1 / len; return self * invLen }
|
||||
|
||||
@inline(__always) mutating func normalise() { let invLen = 1 / len; self *= invLen }
|
||||
|
||||
@inline(__always) func lerp(_ b: Self, _ x: Scalar) -> Self
|
||||
{
|
||||
let invX = 1 - x
|
||||
return Self(self.x * invX + b.x * x, self.y * invX + b.y * x, self.z * invX + b.z * x)
|
||||
}
|
||||
|
||||
@inline(__always) func dot(_ b: Self) -> Scalar { x * b.x + y * b.y + z * b.z }
|
||||
@inline(__always) func cross(_ b: Self) -> Self { Self(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x) }
|
||||
|
||||
@inline(__always) func project(_ n: Self) -> Self { n * self.dot(n) }
|
||||
}
|
||||
|
||||
|
||||
public typealias Vec3f = Vector3<Float>
|
||||
public typealias Vec3d = Vector3<Double>
|
56
Sources/Maths/Vector4.swift
Normal file
56
Sources/Maths/Vector4.swift
Normal file
@ -0,0 +1,56 @@
|
||||
#if USE_SIMD
|
||||
import simd
|
||||
#endif
|
||||
|
||||
|
||||
#if USE_SIMD
|
||||
public typealias Vector4 = SIMD4
|
||||
#else
|
||||
|
||||
public struct Vector4<T: FloatingPoint>: Equatable
|
||||
{
|
||||
public typealias Scalar = T
|
||||
|
||||
public var x, y, z, w: T
|
||||
|
||||
public init() { self.x = 0; self.y = 0; self.z = 0; self.w = 0 }
|
||||
public init(_ x: T, _ y: T, _ z: T, _ w: T) { self.x = x; self.y = y; self.z = z; self.w = w }
|
||||
}
|
||||
|
||||
public extension Vector4
|
||||
{
|
||||
// constants
|
||||
@inline(__always) static var zero: Self { Self(0, 0, 0, 0) }
|
||||
@inline(__always) static var one: Self { Self(1, 1, 1, 1) }
|
||||
|
||||
subscript(index: Int) -> T
|
||||
{
|
||||
get
|
||||
{
|
||||
switch index
|
||||
{
|
||||
case 0: x
|
||||
case 1: y
|
||||
case 2: z
|
||||
case 3: w
|
||||
default: fatalError()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init(_ xyz: Vector3<T>, _ w: T) { self.x = xyz.x; self.y = xyz.y; self.z = xyz.z; self.w = w }
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
public extension Vector4 where Scalar: FloatingPoint
|
||||
{
|
||||
@inline(__always) static var X: Self { Self(1, 0, 0, 0) }
|
||||
@inline(__always) static var Y: Self { Self(0, 1, 0, 0) }
|
||||
@inline(__always) static var Z: Self { Self(0, 0, 1, 0) }
|
||||
@inline(__always) static var W: Self { Self(0, 0, 0, 1) }
|
||||
}
|
||||
|
||||
|
||||
public typealias Vec4f = Vector4<Float>
|
||||
public typealias Vec4d = Vector4<Double>
|
Reference in New Issue
Block a user