-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathvec3.nelua
128 lines (109 loc) · 3.5 KB
/
vec3.nelua
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
global vec3 = @record{
x: number,
y: number,
z: number
}
## vec3.value.is_vec3 = true
local is_vec3_or_scalar = #[concept(function(b)
return b.type.is_vec3 or b.type.is_scalar
end)]#
function vec3.__add(a: is_vec3_or_scalar, b: is_vec3_or_scalar): vec3 <inline,nosideeffect>
## if b.type.is_scalar then
return vec3{a.x+b, a.y+b, a.z+b}
## elseif a.type.is_scalar then
return vec3{a+b.x, a+b.y, a+b.z}
## else
return vec3{a.x+b.x, a.y+b.y, a.z+b.z}
## end
end
function vec3.__sub(a: is_vec3_or_scalar, b: is_vec3_or_scalar): vec3 <inline,nosideeffect>
## if b.type.is_scalar then
return vec3{a.x-b, a.y-b, a.z-b}
## elseif a.type.is_scalar then
return vec3{a-b.x, a-b.y, a-b.z}
## else
return vec3{a.x-b.x, a.y-b.y, a.z-b.z}
## end
end
function vec3.__mul(a: is_vec3_or_scalar, b: is_vec3_or_scalar): vec3 <inline,nosideeffect>
## if b.type.is_scalar then
return vec3{a.x*b, a.y*b, a.z*b}
## elseif a.type.is_scalar then
return vec3{a*b.x, a*b.y, a*b.z}
## else
return vec3{a.x*b.x, a.y*b.y, a.z*b.z}
## end
end
function vec3.__div(a: is_vec3_or_scalar, b: is_vec3_or_scalar): vec3 <inline,nosideeffect>
## if b.type.is_scalar then
local k: number = 1 / b
return vec3{a.x*k, a.y*k, a.z*k}
## elseif a.type.is_scalar then
local k: number = 1 / a
return vec3{k*b.x, k*b.y, k*b.z}
## else
return vec3{a.x/b.x, a.y/b.y, a.z/b.z}
## end
end
function vec3.__unm(a: vec3): vec3 <inline,nosideeffect>
return vec3{-a.x, -a.y, -a.z}
end
function vec3.min(a: vec3, b: vec3): vec3 <inline,nosideeffect>
return vec3{math.min(a.x, b.x), math.min(a.y, b.y), math.min(a.z, b.z)}
end
function vec3.dot(a: vec3, b: vec3): number <inline,nosideeffect>
return a.x*b.x + a.y*b.y + a.z*b.z
end
function vec3.cross(a: vec3, b: vec3): vec3 <inline,nosideeffect>
return vec3{a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x}
end
function vec3.sqrt(a: vec3): vec3 <inline,nosideeffect>
return vec3{math.sqrt(a.x), math.sqrt(a.y), math.sqrt(a.z)}
end
function vec3.squaredlength(v: vec3): number <inline,nosideeffect>
return v.x*v.x + v.y*v.y + v.z*v.z
end
function vec3.length(v: vec3): number <inline,nosideeffect>
return math.sqrt(vec3.squaredlength(v))
end
function vec3.__len(v: vec3): number <inline,nosideeffect>
return math.sqrt(vec3.squaredlength(v))
end
function vec3.unit(v: vec3): vec3 <inline,nosideeffect>
return v / #v
end
function vec3.lerp(a: vec3, b: vec3, t: number): vec3 <inline,nosideeffect>
return a * (1-t) + b * t
end
function vec3.print(v: vec3)
print(v.x, v.y, v.z)
end
function vec3.rotvec(v: vec3, axis: vec3, theta: number): vec3
local n = vec3.unit(axis)
local w = vec3.cross(n, v)
local sint, cost = math.sin(theta), math.cos(theta)
local ns = vec3.dot(v, n) * (1 - cost)
return n * ns + w * sint + v * cost
end
function vec3.random_in_disk(length: number): vec3
local theta = math.fastrand()*math.tau
local sint, cost = math.sin(theta), math.cos(theta)
local rlen = math.sqrt(math.fastrand())*length
return vec3{rlen*cost, rlen*sint, 0}
end
function vec3.random_in_hemisphere(n: vec3)
local theta, len = math.fastrand()*math.tau, math.fastrand()
local w
if math.abs(n.y) > 0.5 then
w = vec3{1,0,0}
else
w = vec3{0,1,0}
end
local u = vec3.unit(vec3.cross(n, w))
local v = vec3.cross(u, n)
local sint, cost = math.sin(theta), math.cos(theta)
local r = math.sqrt(len)
local rx, ry, rz = r*cost, r*sint, math.sqrt(1 - len)
local rr = u * rx + v * ry + n * rz
return vec3.unit(rr)
end