geom.bend

bend-prot@0.1.0.0 · 72 lines · 17 definitions

1import Base
2
3# --- Vec3: a 3D point/vector over F32. Data so it copies freely with `+`. ---
4
5type Vec3 is Data:
6  V3{x: F32, y: F32, z: F32}
7
8def Vec3.add(+a: Vec3, +b: Vec3) -> Vec3:
9  match a b:
10    case V3{+ax, +ay, +az} V3{+bx, +by, +bz}:
11      V3{(ax + bx : F32), (ay + by : F32), (az + bz : F32)}
12
13def Vec3.sub(+a: Vec3, +b: Vec3) -> Vec3:
14  match a b:
15    case V3{+ax, +ay, +az} V3{+bx, +by, +bz}:
16      V3{(ax - bx : F32), (ay - by : F32), (az - bz : F32)}
17
18def Vec3.scale(+s: F32, +v: Vec3) -> Vec3:
19  match v:
20    case V3{+x, +y, +z}:
21      V3{(s * x : F32), (s * y : F32), (s * z : F32)}
22
23def Vec3.dot(+a: Vec3, +b: Vec3) -> F32:
24  match a b:
25    case V3{+ax, +ay, +az} V3{+bx, +by, +bz}:
26      (((ax * bx : F32) + (ay * by : F32) : F32) + (az * bz : F32) : F32)
27
28def Vec3.norm2(+v: Vec3) -> F32:
29  Vec3.dot(v, v)
30
31def Vec3.dist2(+a: Vec3, +b: Vec3) -> F32:
32  Vec3.norm2(Vec3.sub(a, b))
33
34def Vec3.dist(+a: Vec3, +b: Vec3) -> F32:
35  F32.sqrt(Vec3.dist2(a, b))
36
37def Vec3.midpoint(+a: Vec3, +b: Vec3) -> Vec3:
38  Vec3.scale(0.5, Vec3.add(a, b))
39
40def Vec3.cross(+a: Vec3, +b: Vec3) -> Vec3:
41  match a b:
42    case V3{+ax, +ay, +az} V3{+bx, +by, +bz}:
43      V3{((ay * bz : F32) - (az * by : F32) : F32), ((az * bx : F32) - (ax * bz : F32) : F32), ((ax * by : F32) - (ay * bx : F32) : F32)}
44
45def Vec3.sum_coords(v: Vec3) -> F32:
46  match v:
47    case V3{x, y, z}:
48      ((x + y : F32) + z : F32)
49
50def Vec3.neg(+v: Vec3) -> Vec3:
51  match v:
52    case V3{+x, +y, +z}:
53      V3{(0.0 - x : F32), (0.0 - y : F32), (0.0 - z : F32)}
54
55def lerp1(+a: F32, +b: F32, +t: F32) -> F32:
56  (a + ((b - a : F32) * t : F32) : F32)
57
58def Vec3.lerp(+a: Vec3, +b: Vec3, +t: F32) -> Vec3:
59  match a b:
60    case V3{+ax, +ay, +az} V3{+bx, +by, +bz}:
61      V3{lerp1(ax, bx, t), lerp1(ay, by, t), lerp1(az, bz, t)}
62
63# Cosine of the angle between a and b. Undefined for zero vectors.
64def Vec3.cos_angle(+a: Vec3, +b: Vec3) -> F32:
65  (Vec3.dot(a, b) / F32.sqrt((Vec3.norm2(a) * Vec3.norm2(b) : F32)) : F32)
66
67def Vec3.angle(+a: Vec3, +b: Vec3) -> F32:
68  F32.acos(Vec3.cos_angle(a, b))
69
70# Squared area of triangle (a, b, c): |cross(b-a, c-a)|^2 / 4.
71def Vec3.tri_area2(+a: Vec3, +b: Vec3, +c: Vec3) -> F32:
72  (Vec3.norm2(Vec3.cross(Vec3.sub(b, a), Vec3.sub(c, a))) / 4.0 : F32)