aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s+removethis@s-ol.nu>2022-02-03 22:51:29 +0000
committers-ol <s+removethis@s-ol.nu>2025-03-02 14:24:49 +0000
commitd42707433ee198e6faa97b124c3517a51f97c95b (patch)
treeb27f12f18790c295e8f084b3bf00539e3f8e1856
parentlib: rename math → math-simple, add vectorized math (diff)
downloadalive-d42707433ee198e6faa97b124c3517a51f97c95b.tar.gz
alive-d42707433ee198e6faa97b124c3517a51f97c95b.zip
lib: add mat4
-rw-r--r--alv-lib/mat4.moon158
1 files changed, 158 insertions, 0 deletions
diff --git a/alv-lib/mat4.moon b/alv-lib/mat4.moon
new file mode 100644
index 0000000..c36a47d
--- /dev/null
+++ b/alv-lib/mat4.moon
@@ -0,0 +1,158 @@
+import Constant, T, Array, PureOp, any from require "alv.base"
+
+unpack or= table.unpack
+
+vec3 = Array 3, T.num
+vec4 = Array 4, T.num
+mat4 = Array 4, vec4
+
+identity = Constant.meta
+ meta:
+ name: 'identity'
+ summary: "The identity Matrix."
+
+ value: mat4\mk_const {
+ { 1, 0, 0, 0 }
+ { 0, 1, 0, 0 }
+ { 0, 0, 1, 0 }
+ { 0, 0, 0, 1 }
+ }
+
+scale = Constant.meta
+ meta:
+ name: 'scale'
+ summary: "Create a 3d scale matrix."
+ examples: { "(mat4/scale scale)", "(mat4/scale x y z)" }
+ description: "This is a pure op.
+
+`scale` can be a single number for uniform scaling, or an array
+of three numbers that will be used like `x`, `y` and `z`."
+
+ value: class extends PureOp
+ pattern: any.num / (any.num\rep 3, 3) / any(vec3)
+ type: mat4
+ tick: =>
+ scale = @unwrap_all!
+ x, y, z = if "number" == type scale
+ scale, scale, scale
+ else
+ unpack scale
+
+ @out\set {
+ { x, 0, 0, 0 }
+ { 0, y, 0, 0 }
+ { 0, 0, z, 0 }
+ { 0, 0, 0, 1 }
+ }
+
+translate = Constant.meta
+ meta:
+ name: 'translate'
+ summary: "Create a 3d translation matrix."
+ examples: { "(mat4/translate vec)", "(mat4/translate x y z)" }
+ description: "This is a pure op.
+
+`vec` is a num[3] array."
+
+ value: class extends PureOp
+ pattern: (any.num\rep 3, 3) / any(vec3)
+ type: mat4
+ tick: =>
+ { x, y, z } = @unwrap_all!
+
+ @out\set {
+ { 1, 0, 0, 0 }
+ { 0, 1, 0, 0 }
+ { 0, 0, 1, 0 }
+ { x, y, z, 1 }
+ }
+
+rotate = Constant.meta
+ meta:
+ name: 'rotate'
+ summary: "Create a 3d rotation matrix from an axis and angle"
+ examples: { "(mat4/translate axis angle)" }
+ description: "This is a pure op.
+
+`axis` is a num[3] array representing a unit vector."
+
+ value: class extends PureOp
+ pattern: any(vec3) + any.num
+ type: mat4
+ tick: =>
+ { { l, m, n }, a } = @unwrap_all!
+
+ len = math.sqrt l*l + m*m + n*n
+ l, m, n = l/len, m/len, n/len
+
+ ca, sa = (math.cos a), math.sin a
+ na = 1 - ca
+
+ @out\set {
+ {
+ l * l * na + ca
+ l * m * na + n * sa
+ l * n * na - m * sa
+ 0
+ }
+ {
+ m * l * na - n * sa
+ m * m * na + ca
+ m * n * na + l * sa
+ 0
+ }
+ {
+ n * l * na + m * sa
+ n * m * na - l * sa
+ n * n * na + ca
+ 0
+ }
+ { 0, 0, 0, 1 }
+ }
+
+ypr = Constant.meta
+ meta:
+ name: 'yaw-pitch-roll'
+ summary: "Create a 3d rotation matrix from euler angles."
+ examples: { "(yaw-pitch-roll vec3)", "(yaw-pitch-roll y p r)" }
+ description: "This is a pure op."
+
+ value: class extends PureOp
+ pattern: (any.num\rep 3, 3) / any(vec3)
+ type: mat4
+ tick: =>
+ { yaw, pitch, roll } = @unwrap_all!
+
+ ch, sh = math.cos(yaw), math.sin yaw
+ cp, sp = math.cos(pitch), math.sin pitch
+ cb, sb = math.cos(roll), math.sin roll
+
+ @out\set {
+ {
+ ch * cb + sh * sp * sb
+ sb * cp
+ ch * sp * sb - sh * cb
+ 0
+ }
+ {
+ sh * sp * cb - ch * sb
+ cb * cp
+ sb * sh + ch * sp * cb
+ 0
+ }
+ { sh * cp, -sp, ch * cp, 0 }
+ { 0, 0, 0, 1 }
+ }
+
+Constant.meta
+ meta:
+ name: 'mat4'
+ summary: "Operators for generating 4x4 Matrices."
+
+ value:
+ :identity
+ :scale
+ :translate
+ :rotate
+ 'yaw-pitch-roll': ypr
+ '*': mul