-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathTransform.lua
384 lines (216 loc) · 6.78 KB
/
Transform.lua
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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
-- @author Starkkz
module("shadows.Transform", package.seeall)
Object = require("shadows.Object")
Transform = setmetatable( {}, Object )
Transform.__index = Transform
Transform.__type = "Transform"
Transform.x, Transform.y, Transform.z = 0, 0, 0
PI = math.pi
-- @description: Creates a new transformation
function Transform:new()
local self = setmetatable({}, Transform)
self.Children = {}
self.Matrix = { {}, {} }
self.InverseMatrix = { {}, {} }
self:SetLocalRotation(0)
return self
end
-- @description: Assigns a transform as a parent of another transform (Makes the coordinates of a transform local to another)
function Transform:SetParent(Parent)
if self.Parent then
self.Parent.Children[ self.ID ] = nil
end
if Parent then
self.ID = #Parent.Children + 1
self.Parent = Parent
Parent.Children[ self.ID ] = self
else
self.ID = nil
self.Parent = nil
end
end
-- @description: Gets the parent transform of a transform
function Transform:GetParent()
return self.Parent
end
-- @description: Tells the children that the transform has changed
function Transform:Change()
self.HasChanged = true
for ID, Child in pairs(self.Children) do
Child:Change()
end
end
-- @description: Sets the local rotation of a transform
function Transform:SetLocalRotation(Angle)
while Angle < -180 do
Angle = Angle + 360
end
while Angle > 180 do
Angle = Angle - 360
end
if Angle ~= self.Rotation then
self.Rotation = Angle
self.Radians = math.rad(Angle)
if Angle == 0 then
self.Matrix[1][1] = 1
self.Matrix[1][2] = 0
self.Matrix[2][1] = 0
self.Matrix[2][2] = 1
self.InverseMatrix[1][1] = 1
self.InverseMatrix[1][2] = 0
self.InverseMatrix[2][1] = 0
self.InverseMatrix[2][2] = 1
else
local Cosine = math.cos(self.Radians)
local Sine = math.sin(self.Radians)
-- The transformation matrix
self.Matrix[1][1] = Cosine
self.Matrix[1][2] = -Sine
self.Matrix[2][1] = Sine
self.Matrix[2][2] = Cosine
local a = self.Matrix[1][1]
local b = self.Matrix[1][2]
local c = self.Matrix[2][1]
local d = self.Matrix[2][2]
local Multiplier = 1 / ( a * d - b * c )
self.InverseMatrix[1][1] = d * Multiplier
self.InverseMatrix[1][2] = -b * Multiplier
self.InverseMatrix[2][1] = -c * Multiplier
self.InverseMatrix[2][2] = a * Multiplier
end
self:Change()
return true
end
end
-- @description: Gets the local rotation of a transform
function Transform:GetLocalRotation()
return self.Rotation
end
-- @description: Gets the local rotation of a transform in radians
function Transform:GetLocalRadians()
return self.Radians
end
-- @description: Sets the rotation of a transform
function Transform:SetRotation(Angle)
if self.Parent then
Angle = Angle - self.Parent:GetRotation()
end
return self:SetLocalRotation(Angle)
end
-- @description: Gets the rotation of a transform + SumRotation in degrees
function Transform:GetRotation(SumRotation)
local Rotation = self.Rotation + (SumRotation or 0)
if self.Parent then
Rotation = Rotation + self.Parent:GetRotation()
end
while Rotation < -180 do
Rotation = Rotation + 360
end
while Rotation > 180 do
Rotation = Rotation - 360
end
return Rotation
end
-- @description: Gets the rotation of a transform + SumRadians in radians
function Transform:GetRadians(SumRadians)
local Rotation = self.Radians + (SumRadians or 0)
if self.Parent then
Rotation = Rotation + self.Parent:GetRadians()
end
while Rotation < -PI do
Rotation = Rotation + PI * 2
end
while Rotation > PI do
Rotation = Rotation - PI * 2
end
return Rotation
end
-- @description: Sets the local position of a transform
function Transform:SetLocalPosition(x, y, z)
if x ~= self.x or y ~= self.y or ( z and z ~= self.z ) then
if z then
self.z = z
end
self.x, self.y = x, y
self:Change()
return true
end
return false
end
-- @description: Gets the local position of a transform
function Transform:GetLocalPosition()
return self.x, self.y, self.z
end
-- @description: Sets the position of a transform
function Transform:SetPosition(x, y, z)
if self.Parent then
x, y, z = self.Parent:ToLocal(x, y, z)
end
return self:SetLocalPosition(x, y, z)
end
-- @description: Gets the position of a transform
function Transform:GetPosition()
if self.Parent then
return self.Parent:ToWorld(self.x, self.y, self.z)
end
return self.x, self.y, self.z
end
-- @description: Gets the position of a transform as a vector
function Transform:GetPositionVector()
if self.Parent then
local x, y, z = self.Parent:ToWorld(self.x, self.y, self.z)
return {x = x, y = y, z = z}
end
return {x = self.x, y = self.y, z = self.z}
end
-- @description: Transforms a point to world coordinates
function Transform:ToWorld(x, y, z)
if self.Parent then
return self.Parent:ToWorld( self.x + self.Matrix[1][1] * x + self.Matrix[1][2] * y, self.y + self.Matrix[2][1] * x + self.Matrix[2][2] * y, self.z + ( z or 0 ) )
end
return self.x + tonumber( self.Matrix[1][1] * x + self.Matrix[1][2] * y ), self.y + tonumber( self.Matrix[2][1] * x + self.Matrix[2][2] * y ), self.z + ( z or 0 )
end
-- @description: Transform multiple points to world coordinates (does not support 'z' coordinate)
function Transform:ToWorldPoints(Points)
local TransformedPoints = {}
for i = 1, #Points, 2 do
local x, y = Points[i], Points[i + 1]
TransformedPoints[i] = self.x + tonumber( self.Matrix[1][1] * x + self.Matrix[1][2] * y )
TransformedPoints[i + 1] = self.y + tonumber( self.Matrix[2][1] * x + self.Matrix[2][2] * y )
end
if self.Parent then
return self.Parent:ToWorldPoints(TransformedPoints)
end
return TransformedPoints
end
-- @description: Transforms a point to local coordinates
function Transform:ToLocal(x, y, z)
if self.Parent then
x, y, z = self.Parent:ToLocal(x, y, z)
end
x, y, z = x - self.x, y - self.y, z - self.z
return tonumber( self.InverseMatrix[1][1] * x + self.InverseMatrix[1][2] * y ), tonumber( self.InverseMatrix[2][1] * x + self.InverseMatrix[2][2] * y ), z
end
-- @description: Transform a local angle to world
function Transform:ToWorldAngle(Angle)
local Rotation = Angle + self:GetRotation()
while Rotation < -180 do
Rotation = Rotation + 360
end
while Rotation > 180 do
Rotation = Rotation - 360
end
return Rotation
end
-- @description: Transform a world angle to local
function Transform:ToLocalAngle(Angle)
local Rotation = Angle - self:GetRotation()
while Rotation < -180 do
Rotation = Rotation + 360
end
while Rotation > 180 do
Rotation = Rotation - 360
end
return Rotation
end
return Transform