-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.py
162 lines (148 loc) · 5.72 KB
/
utils.py
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
159
160
161
162
from functools import partial
from collections import namedtuple
import math
from numbers import Number
from collections.abc import Iterable
SQRT_2 = 1.41421356237
SQRT_3 = 1.73205080757
def lerp(a, b, t):
return a*(1-t) + b*t
def clamp(a, lo, hi):
return min(hi, max(lo, a))
def smoothstep(x, lo, hi):
x = clamp((x - lo) / (hi - lo), 0, 1)
return x*x * (3 - 2 * x)
def smin(a, b, k):
h = max(k-abs(a-b), 0)
return min(a, b) - (h*h)/(4*k)
def smax(a, b, k):
h = max(k-abs(a-b), 0)
return max(a, b) + (h*h)/(4*k)
class vec2(namedtuple('vec2', ['x', 'y'])):
def __new__(cls, x, y=None):
y = x if y is None else y
return super().__new__(cls, x, y)
def __add__(self, other):
return vec2(self.x+other.x, self.y+other.y)
def __mul__(self, other):
if not isinstance(other, Number):
return NotImplemented
return vec2(other*self.x, other*self.y)
def __rmul__(self, other):
if not isinstance(other, Number):
return NotImplemented
return vec2(other*self.x, other*self.y)
def __truediv__(self, other):
return vec2(self.x/other, self.y/other)
def __floordiv__(self, other):
return vec2(self.x//other, self.y//other)
def __sub__(self, other):
return vec2(self.x-other.x, self.y-other.y)
def __neg__(self):
return vec2(-self.x, -self.y)
def mag(self):
return math.sqrt(self.x*self.x + self.y*self.y)
def normalize(self):
return self/self.mag()
def dot(self, other):
return self.x*other.x + self.y*other.y
def __repr__(self):
return 'vec2({:.2f}, {:.2f})'.format(self.x, self.y)
def __getattr__(self, swiz):
if len(swiz) == 2:
return vec2(*(getattr(self, a) for a in swiz))
if len(swiz) == 3:
return vec3(*(getattr(self, a) for a in swiz))
if len(swiz) == 4:
return vec4(*(getattr(self, a) for a in swiz))
def rotate(self, angle):
angle = math.radians(angle)
c = math.cos(angle)
s = math.sin(angle)
return vec2(
self.x*c - self.y*s,
self.x*s + self.y*c,
)
class vec3(namedtuple('vec3', ['x', 'y', 'z'])):
def __new__(cls, x, y=None, z=None):
y = x if y is None else y
z = y if z is None else z
return super().__new__(cls, x, y, z)
def __add__(self, other):
return vec3(self.x+other.x, self.y+other.y, self.z+other.z)
def __mul__(self, other):
if not isinstance(other, Number):
return NotImplemented
return vec3(other*self.x, other*self.y, other*self.z)
def __rmul__(self, other):
if not isinstance(other, Number):
return NotImplemented
return vec3(other*self.x, other*self.y, other*self.z)
def __truediv__(self, other):
return vec3(self.x/other, self.y/other, self.z/other)
def __floordiv__(self, other):
return vec3(self.x//other, self.y//other, self.z//other)
def __sub__(self, other):
return vec3(self.x-other.x, self.y-other.y, self.z-other.z)
def __neg__(self):
return vec3(-self.x, -self.y, -self.z)
def mag(self):
return math.sqrt(self.x*self.x + self.y*self.y + self.z*self.z)
def normalize(self):
return self/self.mag()
def dot(self, other):
return self.x*other.x + self.y*other.y + self.z*other.z
def cross(self, other):
return vec3(
self.y*other.z - self.z*other.y,
self.z*other.x - self.x*other.z,
self.x*other.y - self.y*other.x
)
def __repr__(self):
return 'vec3({:.2f}, {:.2f}, {:.2f})'.format(self.x, self.y, self.z)
def __getattr__(self, swiz):
if len(swiz) == 2:
return vec2(*(getattr(self, a) for a in swiz))
if len(swiz) == 3:
return vec3(*(getattr(self, a) for a in swiz))
if len(swiz) == 4:
return vec4(*(getattr(self, a) for a in swiz))
class vec4(namedtuple('vec4', ['x', 'y', 'z', 'w'])):
def __new__(cls, x, y=None, z=None, w=None):
y = x if y is None else y
z = y if z is None else z
w = r if w is None else w
return super().__new__(cls, x, y, z, w)
def __add__(self, other):
return vec4(self.x+other.x, self.y+other.y, self.z+other.z, self.w+other.w)
def __mul__(self, other):
if not isinstance(other, Number):
return NotImplemented
return vec4(other*self.x, other*self.y, other*self.z, other*self.w)
def __rmul__(self, other):
if not isinstance(other, Number):
return NotImplemented
return vec4(other*self.x, other*self.y, other*self.z, other*self.w)
def __truediv__(self, other):
return vec4(self.x/other, self.y/other, self.z/other, self.w/other)
def __floordiv__(self, other):
return vec4(self.x//other, self.y//other, self.z//other, self.w//other)
def __sub__(self, other):
return vec4(self.x-other.x, self.y-other.y, self.z-other.z, self.w-other.w)
def __neg__(self):
return vec4(-self.x, -self.y, -self.z, -self.w)
def mag(self):
return math.sqrt(self.x*self.x + self.y*self.y + self.z*self.z + self.w*self.w)
def normalize(self):
return self/self.mag()
def dot(self, other):
return self.x*other.x + self.y*other.y + self.z*other.z + self.w*other.w
def __repr__(self):
return 'vec4({:.2f}, {:.2f}, {:.2f}, {:.2f})'.format(self.x, self.y, self.z, self.w)
def __getattr__(self, swiz):
if len(swiz) == 2:
return vec2(*(getattr(self, a) for a in swiz))
if len(swiz) == 3:
return vec3(*(getattr(self, a) for a in swiz))
if len(swiz) == 4:
return vec4(*(getattr(self, a) for a in swiz))