-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathLerps.lua
265 lines (224 loc) · 9.47 KB
/
Lerps.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
-- Lerp functions for most data types, featuring CIELUV Color Lerping
-- @author Validark
-- @author Fraktality
-- @author Sharksie (NumberSequence Lerp)
-- Fraktality's code is released under the MIT license:
-- Copyright 2017 Parker Stebbins <[email protected]>
--
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software
-- and associated documentation files (the "Software"), to deal in the Software without
-- restriction, including without limitation the rights to use, copy, modify, merge, publish,
-- distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
-- Software is furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in all copies or
-- substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--
local Resources = require(game:GetService("ReplicatedStorage"):WaitForChild("Resources"))
local Table = Resources:LoadLibrary("Table")
local function Lerp(Start, Finish, Alpha)
return Start + Alpha * (Finish - Start)
end
local Color3Lerp do
-- Combines two colors in CIELUV space.
-- Color3 LerpCIELUV(Color3 fromColor, Color3 toColor, float t)
-- @author Fraktality
-- https://www.w3.org/Graphics/Color/srgb
local Black = Color3.fromRGB(0, 0, 0)
function Color3Lerp(c0, c1, t)
local u0, v0, u1, v1
-- Convert from linear RGB to scaled CIELUV (RgbToLuv13)
local r, g, b = c0.r, c0.g, c0.b
-- Apply inverse gamma correction
r = r < 0.0404482362771076 and r/12.92 or 0.87941546140213*(r + 0.055)^2.4
g = g < 0.0404482362771076 and g/12.92 or 0.87941546140213*(g + 0.055)^2.4
b = b < 0.0404482362771076 and b/12.92 or 0.87941546140213*(b + 0.055)^2.4
-- sRGB->XYZ->CIELUV
local y = 0.2125862307855956*r + 0.71517030370341085*g + 0.0722004986433362*b
local z = 3.6590806972265883*r + 11.4426895800574232*g + 4.1149915024264843*b
local l0 = y > 0.008856451679035631 and 116*y^(1/3) - 16 or 903.296296296296*y
if z > 1e-15 then
u0, v0 = l0*(0.9257063972951867*r - 0.8333736323779866*g - 0.09209820666085898*b)/z, l0*(9*y/z - 0.46832)
else
u0, v0 = -0.19783*l0, -0.46832*l0
end
-- Convert from linear RGB to scaled CIELUV (RgbToLuv13)
r, g, b = c1.r, c1.g, c1.b
-- Apply inverse gamma correction
r = r < 0.0404482362771076 and r/12.92 or 0.87941546140213*(r + 0.055)^2.4
g = g < 0.0404482362771076 and g/12.92 or 0.87941546140213*(g + 0.055)^2.4
b = b < 0.0404482362771076 and b/12.92 or 0.87941546140213*(b + 0.055)^2.4
-- sRGB->XYZ->CIELUV
y = 0.2125862307855956*r + 0.71517030370341085*g + 0.0722004986433362*b
z = 3.6590806972265883*r + 11.4426895800574232*g + 4.1149915024264843*b
local l1 = y > 0.008856451679035631 and 116*y^(1/3) - 16 or 903.296296296296*y
if z > 1e-15 then
u1, v1 = l1*(0.9257063972951867*r - 0.8333736323779866*g - 0.09209820666085898*b)/z, l1*(9*y/z - 0.46832)
else
u1, v1 = -0.19783*l1, -0.46832*l1
end
-- The inputs aren't needed anymore, so don't drag out their lifetimes
-- c0, c1 = nil, nil
-- return function(t)
-- Interpolate
local l = (1 - t)*l0 + t*l1
if l < 0.0197955 then
return Black
end
local u = ((1 - t)*u0 + t*u1)/l + 0.19783
local v = ((1 - t)*v0 + t*v1)/l + 0.46832
-- CIELUV->XYZ
y = (l + 16)/116
y = y > 0.206896551724137931 and y*y*y or 0.12841854934601665*y - 0.01771290335807126
local x = y*u/v
z = y*((3 - 0.75*u)/v - 5)
-- XYZ->linear sRGB
r = 7.2914074*x - 1.5372080*y - 0.4986286*z
g = -2.1800940*x + 1.8757561*y + 0.0415175*z
b = 0.1253477*x - 0.2040211*y + 1.0569959*z
-- Adjust for the lowest out-of-bounds component
if r < 0 and r < g and r < b then
r, g, b = 0, g - r, b - r
elseif g < 0 and g < b then
r, g, b = r - g, 0, b - g
elseif b < 0 then
r, g, b = r - b, g - b, 0
end
-- Apply gamma correction
r = r < 3.1306684425e-3 and 12.92*r or 1.055*r^(1/2.4) - 0.055
g = g < 3.1306684425e-3 and 12.92*g or 1.055*g^(1/2.4) - 0.055
b = b < 3.1306684425e-3 and 12.92*b or 1.055*b^(1/2.4) - 0.055
return Color3.new(
-- Clamp the result
r > 1 and 1 or r < 0 and 0 or r,
g > 1 and 1 or g < 0 and 0 or g,
b > 1 and 1 or b < 0 and 0 or b
)
-- end
end
end
local function sortByTime(a, b)
return a.Time < b.Time
end
return Table.Lock {
number = Lerp;
Color3 = Color3Lerp;
UDim2 = UDim2.new().Lerp;
CFrame = CFrame.new().Lerp;
Vector2 = Vector2.new().Lerp;
Vector3 = Vector3.new().Lerp;
string = function(start, finish, alpha)
-- Very simple, doesn't yet take into account previous string
local count = #finish
local a = 1 + count*alpha
return finish:sub(1, a < count and a or count)
end;
UDim = function(start, finish, alpha)
return UDim.new(Lerp(start.Scale, finish.Scale, alpha), Lerp(start.Offset, finish.Offset, alpha))
end;
Rect = function(start, finish, alpha)
return Rect.new(
Lerp(start.Min.X, finish.Min.X, alpha), Lerp(start.Min.Y, finish.Min.Y, alpha),
Lerp(start.Max.X, finish.Max.X, alpha), Lerp(start.Max.Y, finish.Max.Y, alpha)
)
end;
PhysicalProperties = function(start, finish, alpha)
return PhysicalProperties.new(
Lerp(start.Density, finish.Density, alpha),
Lerp(start.Friction, finish.Friction, alpha),
Lerp(start.Elasticity, finish.Elasticity, alpha),
Lerp(start.FrictionWeight, finish.FrictionWeight, alpha),
Lerp(start.ElasticityWeight, finish.ElasticityWeight, alpha)
)
end;
NumberRange = function(start, finish, alpha)
return NumberRange.new(Lerp(start.Min, finish.Min, alpha), Lerp(start.Max, finish.Max, alpha))
end;
ColorSequence = function(start, finish, alpha)
return ColorSequence.new(Color3Lerp(start[1], finish[1], alpha), Color3Lerp(start[2], finish[2], alpha))
end;
Region3 = function(start, finish, alpha) -- @author Sharksie
local imin = Lerp(start.CFrame * (-start.Size*0.5), finish.CFrame * (-finish.Size*0.5), alpha)
local imax = Lerp(start.CFrame * ( start.Size*0.5), finish.CFrame * ( finish.Size*0.5), alpha)
local iminx = imin.x
local imaxx = imax.x
local iminy = imin.y
local imaxy = imax.y
local iminz = imin.z
local imaxz = imax.z
return Region3.new(
Vector3.new(iminx < imaxx and iminx or imaxx, iminy < imaxy and iminy or imaxy, iminz < imaxz and iminz or imaxz),
Vector3.new(iminx > imaxx and iminx or imaxx, iminy > imaxy and iminy or imaxy, iminz > imaxz and iminz or imaxz)
)
end;
NumberSequence = function(start, finish, alpha)
-- @author Sharksie
-- For each point on each line, find the values of the other sequence at that point in time through interpolation
-- then interpolate between the known value and the learned value
-- then use that value to create a new keypoint at the time
-- then build a new sequence using all the keypoints generated
local keypoints = {}
local addedTimes = {}
for i, ap in next, start.Keypoints do
local closestAbove, closestBelow
for i, bp in next, finish.Keypoints do
if bp.Time == ap.Time then
closestAbove, closestBelow = bp, bp
break
elseif bp.Time < ap.Time and (closestBelow == nil or bp.Time > closestBelow.Time) then
closestBelow = bp
elseif bp.Time > ap.Time and (closestAbove == nil or bp.Time < closestAbove.Time) then
closestAbove = bp
end
end
local bValue, bEnvelope
if closestAbove == closestBelow then
bValue, bEnvelope = closestAbove.Value, closestAbove.Envelope
else
local p = (ap.Time - closestBelow.Time)/(closestAbove.Time - closestBelow.Time)
bValue = (closestAbove.Value - closestBelow.Value)*p + closestBelow.Value
bEnvelope = (closestAbove.Envelope - closestBelow.Envelope)*p + closestBelow.Envelope
end
local interValue = (bValue - ap.Value)*alpha + ap.Value
local interEnvelope = (bEnvelope - ap.Envelope)*alpha + ap.Envelope
local interp = NumberSequenceKeypoint.new(ap.Time, interValue, interEnvelope)
table.insert(keypoints, interp)
addedTimes[ap.Time] = true
end
for i, bp in next, finish.Keypoints do
if not addedTimes[bp.Time] then
local closestAbove, closestBelow
for i, ap in next, start.Keypoints do
if ap.Time == bp.Time then
closestAbove, closestBelow = ap, ap
break
elseif ap.Time < bp.Time and (closestBelow == nil or ap.Time > closestBelow.Time) then
closestBelow = ap
elseif ap.Time > bp.Time and (closestAbove == nil or ap.Time < closestAbove.Time) then
closestAbove = ap
end
end
local aValue, aEnvelope
if closestAbove == closestBelow then
aValue, aEnvelope = closestAbove.Value, closestAbove.Envelope
else
local p = (bp.Time - closestBelow.Time)/(closestAbove.Time - closestBelow.Time)
aValue = (closestAbove.Value - closestBelow.Value)*p + closestBelow.Value
aEnvelope = (closestAbove.Envelope - closestBelow.Envelope)*p + closestBelow.Envelope
end
local interValue = (bp.Value - aValue)*alpha + aValue
local interEnvelope = (bp.Envelope - aEnvelope)*alpha + aEnvelope
local interp = NumberSequenceKeypoint.new(bp.Time, interValue, interEnvelope)
table.insert(keypoints, interp)
end
end
table.sort(keypoints, sortByTime)
return NumberSequence.new(keypoints)
end;
}