aboutsummaryrefslogtreecommitdiffstats
path: root/alv-lib/mat4.moon
blob: c36a47d1b31eddcc5ffdc0dd206bd4fdf2a41a4b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
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