240 lines
7.1 KiB
Odin
240 lines
7.1 KiB
Odin
package sectr
|
|
|
|
/*
|
|
Vec3 : 3D Vector (x, y, z) (3x1) 4D Expression : (x, y, z, 0)
|
|
Bivec3 : 3D Bivector (yz, zx, xy) (3x1)
|
|
Trivec3 : 3D Trivector (xyz) (1x1)
|
|
Rotor3 : 3D Rotation Versor-Transform (4x1)
|
|
Motor3 : 3D Rotation & Translation Transform (4x2)
|
|
*/
|
|
|
|
Vec3 :: [3]f32
|
|
Vec4 :: [4]f32
|
|
|
|
Bivec3 :: struct #raw_union {
|
|
using _ : struct { yz, zx, xy : f32 },
|
|
using xyz : Vec3,
|
|
}
|
|
|
|
Trivec3 :: distinct f32
|
|
|
|
Rotor3 :: struct {
|
|
using bv : Bivec3,
|
|
s : f32, // Scalar
|
|
}
|
|
|
|
Shifter3 :: struct {
|
|
using bv : Bivec3,
|
|
s : f32, // Scalar
|
|
}
|
|
|
|
Motor3 :: struct {
|
|
rotor : Rotor3,
|
|
md : Shifter3,
|
|
}
|
|
|
|
UnitVec3 :: distinct Vec3
|
|
UnitVec4 :: distinct Vec4
|
|
UnitBivec3 :: distinct Bivec3
|
|
|
|
//region Vec3
|
|
|
|
vec3_via_f32s :: #force_inline proc "contextless" (x, y, z : f32) -> Vec3 { return {x, y, z} }
|
|
|
|
// complement_vec3 :: #force_inline proc "contextless" ( v : Vec3 ) -> Bivec3 {return transmute(Bivec3) v}
|
|
|
|
cross_vec3 :: proc "contextless" (a, b : Vec3) -> (v : Vec3) {
|
|
v = vec3( wedge(a, b))
|
|
return
|
|
}
|
|
|
|
dot_vec3 :: proc "contextless" ( a, b : Vec3 ) -> (s : f32) {
|
|
mult := a * b // array multiply
|
|
s = mult.x + mult.y + mult.z
|
|
return
|
|
}
|
|
|
|
inverse_mag_vec3 :: proc "contextless" (v : Vec3) -> (result : f32) {
|
|
square := pow2(v)
|
|
result = inverse_sqrt( square )
|
|
return
|
|
}
|
|
|
|
magnitude_vec3 :: proc "contextless" (v : Vec3) -> (mag : f32) {
|
|
square := pow2(v)
|
|
mag = sqrt(square)
|
|
return
|
|
}
|
|
|
|
normalize_vec3 :: proc "contextless" (v : Vec3) -> (unit_v : UnitVec3) {
|
|
unit_v = transmute(UnitVec3) (v * inverse_mag(v))
|
|
return
|
|
}
|
|
|
|
pow2_vec3 :: #force_inline proc "contextless" ( v : Vec3 ) -> (s : f32) { return dot(v, v) }
|
|
|
|
project_vec3 :: proc "contextless" ( a, b : Vec3 ) -> ( a_to_b : Vec3 ) {
|
|
return
|
|
}
|
|
|
|
reject_vec3 :: proc "contextless" ( a, b : Vec3 ) -> ( a_from_b : Vec3 ) {
|
|
return
|
|
}
|
|
|
|
project_v3_unitv3 :: proc "contextless" ( v : Vec3, u : UnitVec3 ) -> (v_to_u : Vec3) {
|
|
inner := dot(v, u)
|
|
v_to_u = (transmute(Vec3) u) * inner
|
|
return
|
|
}
|
|
project_unitv3_v3 :: #force_inline proc "contextless" (u : UnitVec3, v : Vec3) -> (u_to_v : Vec3) {
|
|
inner := dot(u, v)
|
|
u_to_v = v * inner
|
|
return
|
|
}
|
|
|
|
// Anti-wedge of vectors
|
|
regress_vec3 :: proc "contextless" ( a, b : Vec3 ) -> f32 {
|
|
return a.x * b.y - a.y * b.x
|
|
}
|
|
|
|
reject_v3_unitv3 :: proc "contextless" ( v : Vec3, u : UnitVec3 ) -> ( v_from_u : Vec3) {
|
|
inner := dot(v, u)
|
|
v_from_u = (v - (transmute(Vec3) u)) * inner
|
|
return
|
|
}
|
|
reject_unitv3_v3 :: proc "contextless" ( v : Vec3, u : UnitVec3 ) -> ( u_from_v : Vec3) {
|
|
inner := dot(u, v)
|
|
u_from_v = ((transmute(Vec3) u) - v) * inner
|
|
return
|
|
}
|
|
|
|
// Combines the deimensions that are present in a & b
|
|
wedge_vec3 :: proc "contextless" (a, b : Vec3) -> (bv : Bivec3) {
|
|
yzx_zxy := a.yzx * b.zxy
|
|
zxy_yzx := a.zxy * b.yzx
|
|
bv = transmute(Bivec3) (yzx_zxy - zxy_yzx)
|
|
return
|
|
}
|
|
|
|
//endregion Vec3
|
|
|
|
//region Bivec3
|
|
bivec3_via_f32s :: #force_inline proc "contextless" (yz, zx, xy : f32) -> Bivec3 {return { xyz = {yz, zx, xy} }}
|
|
|
|
complement_bivec3 :: #force_inline proc "contextless" (b : Bivec3) -> Bivec3 {return transmute(Bivec3) b.xyz}
|
|
|
|
//region Operations isomoprhic to vectors
|
|
negate_bivec3 :: #force_inline proc "contextless" (b : Bivec3) -> Bivec3 {return transmute(Bivec3) -b.xyz}
|
|
add_bivec3 :: #force_inline proc "contextless" (a, b : Bivec3) -> Bivec3 {return transmute(Bivec3) (a.xyz + b.xyz)}
|
|
sub_bivec3 :: #force_inline proc "contextless" (a, b : Bivec3) -> Bivec3 {return transmute(Bivec3) (a.xyz - b.xyz)}
|
|
mul_bivec3 :: #force_inline proc "contextless" (a, b : Bivec3) -> Bivec3 {return transmute(Bivec3) (a.xyz * b.xyz)}
|
|
mul_bivec3_f32 :: #force_inline proc "contextless" (b : Bivec3, s : f32) -> Bivec3 {return transmute(Bivec3) (b.xyz * s)}
|
|
mul_f32_bivec3 :: #force_inline proc "contextless" (s : f32, b : Bivec3) -> Bivec3 {return transmute(Bivec3) (s * b.xyz)}
|
|
div_bivec3_f32 :: #force_inline proc "contextless" (b : Bivec3, s : f32) -> Bivec3 {return transmute(Bivec3) (b.xyz / s)}
|
|
inverse_mag_bivec3 :: #force_inline proc "contextless" (b : Bivec3) -> f32 {return inverse_mag_vec3(b.xyz)}
|
|
magnitude_bivec3 :: #force_inline proc "contextless" (b : Bivec3) -> f32 {return magnitude_vec3 (b.xyz)}
|
|
normalize_bivec3 :: #force_inline proc "contextless" (b : Bivec3) -> UnitBivec3 {return transmute(UnitBivec3) normalize_vec3(b.xyz)}
|
|
squared_mag_bivec3 :: #force_inline proc "contextless" (b : Bivec3) -> f32 {return pow2_vec3(b.xyz)}
|
|
//endregion Operations isomoprhic to vectors
|
|
|
|
// The wedge of a bi-vector in 3D vector space results in a Trivector represented as a scalar.
|
|
// This scalar usually resolves to zero with six possible exceptions that lead to the negative volume element.
|
|
wedge_bivec3 :: proc ( a, b : Bivec3 ) -> f32 {
|
|
s := a.yz + b.yz + a.zx + b.zx + a.xy + b.xy
|
|
return s
|
|
}
|
|
|
|
// anti-wedge (Combines dimensions that are absent from a & b)
|
|
regress_bivec3 :: #force_inline proc "contextless" ( a, b : Bivec3 ) -> Vec3 {return wedge_vec3(vec3(a), vec3(b))}
|
|
regress_bivec3_v :: #force_inline proc "contextless" (b : Bivec3, v : Vec3) -> f32 {return regress_vec3(b.xyz, v)}
|
|
regress_v3_bivec3 :: #force_inline proc "contextless" (v : Vec3, b : Bivec3) -> f32 {return regress_vec3(b.xyz, v)}
|
|
|
|
//endregion Bivec3
|
|
|
|
//region Rotor3
|
|
|
|
rotor3_via_comps :: proc "contextless" (yz, zx, xy, scalar : f32) -> (rotor : Rotor3) {
|
|
rotor = Rotor3 {bivec3_via_f32s(yz, zx, xy), scalar}
|
|
return
|
|
}
|
|
|
|
rotor3_via_bv_s :: proc "contextless" (bv : Bivec3, scalar : f32) -> (rotor : Rotor3) {
|
|
rotor = Rotor3 {bv, scalar}
|
|
return
|
|
}
|
|
|
|
rotor3_via_from_to :: proc "contextless" ( from, to : Vec3 ) -> (rotor : Rotor3) {
|
|
scalar := 1 + dot( from, to )
|
|
return
|
|
}
|
|
|
|
inverse_mag_rotor3 :: proc "contextless" (rotor : Rotor3) -> (s : f32) {
|
|
return
|
|
}
|
|
|
|
magnitude_rotor3 :: proc "contextless" (rotor : Rotor3) -> (s : f32) {
|
|
return
|
|
}
|
|
|
|
squared_mag :: proc "contextless" (rotor : Rotor3) -> (s : f32) {
|
|
return
|
|
}
|
|
|
|
reverse_rotor3 :: proc "contextless" (rotor : Rotor3) -> (reversed : Rotor3) {
|
|
reversed = { negate_bivec3(rotor.bv), rotor.s }
|
|
return
|
|
}
|
|
|
|
//endregion Rotor3
|
|
|
|
//region Flat Projective Geometry
|
|
|
|
Point3 :: distinct Vec3
|
|
PointFlat3 :: distinct Vec4
|
|
Line3 :: struct {
|
|
weight : Vec3,
|
|
bulk : Bivec3,
|
|
}
|
|
Plane3 :: distinct Vec4 // 4D Anti-vector
|
|
|
|
// aka: wedge operation for points
|
|
join_point3 :: proc "contextless" (p, q : Point3) -> (l : Line3) {
|
|
weight := sub(q, p)
|
|
bulk := wedge(vec3(p), vec3(q))
|
|
l = {weight, bulk}
|
|
return
|
|
}
|
|
|
|
join_pointflat3 :: proc "contextless" (p, q : PointFlat3) -> (l : Line3) {
|
|
weight := vec3(
|
|
p.w * q.x - p.x * q.w,
|
|
p.w * q.y - p.y * q.w,
|
|
p.w * q.z - p.z * q.w
|
|
)
|
|
bulk := wedge(vec3(p), vec3(q))
|
|
l = { weight, bulk}
|
|
return
|
|
}
|
|
|
|
sub_point3 :: proc "contextless" (a, b : Point3) -> (v : Vec3) {
|
|
v = vec3(a) - vec3(b)
|
|
return
|
|
}
|
|
|
|
//endregion Flat Projective Geometry
|
|
|
|
//region Rational Trig
|
|
|
|
quadrance :: proc "contextless" (a, b : Point3) -> (q : f32) {
|
|
q = pow2( sub(a, b))
|
|
return
|
|
}
|
|
|
|
// Assumes the weight component is normalized.
|
|
spread :: proc "contextless" (l, m : Line3) -> (s : f32) {
|
|
s = dot(l.weight, m.weight)
|
|
return
|
|
}
|
|
|
|
//endregion Rational Trig
|