mirror of
https://github.com/centau/vide.git
synced 2026-08-20 14:41:37 +00:00
Merge pull request #61 from ernisto/fix/spring
fix(spring tolerance): guarantee a minimun movement to goal
This commit is contained in:
commit
0e41514860
1 changed files with 28 additions and 19 deletions
|
|
@ -9,8 +9,6 @@ local update_descendants = graph.update_descendants
|
||||||
local push_scope_as_child_of = graph.push_scope_as_child_of
|
local push_scope_as_child_of = graph.push_scope_as_child_of
|
||||||
|
|
||||||
local UPDATE_RATE = 120
|
local UPDATE_RATE = 120
|
||||||
local TOLERANCE = 0.001
|
|
||||||
local TOLERANCE_VECTOR = vector.create(TOLERANCE, TOLERANCE, TOLERANCE)
|
|
||||||
|
|
||||||
type Animatable = number | CFrame | Color3 | UDim | UDim2 | Vector2 | Vector3
|
type Animatable = number | CFrame | Color3 | UDim | UDim2 | Vector2 | Vector3
|
||||||
|
|
||||||
|
|
@ -232,6 +230,24 @@ local function spring<T>(source: () -> T, period: number?, damping_ratio: number
|
||||||
end, config
|
end, config
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- luau vectors have f32 for each component, unlike luau number which is f64
|
||||||
|
local FLOAT32_MANTISSA_BITS = 23
|
||||||
|
type float32 = number
|
||||||
|
|
||||||
|
local function get_min_step(x: float32)
|
||||||
|
local _,exponent = math.frexp(x)
|
||||||
|
|
||||||
|
local lower_mantissa = math.ldexp(1, -FLOAT32_MANTISSA_BITS - 1)
|
||||||
|
return math.ldexp(lower_mantissa, exponent)
|
||||||
|
end
|
||||||
|
local function get_min_vector_step(goal: vector): vector
|
||||||
|
return vector.create(
|
||||||
|
get_min_step(goal.x),
|
||||||
|
get_min_step(goal.y),
|
||||||
|
get_min_step(goal.z)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
local function step_springs(dt: number)
|
local function step_springs(dt: number)
|
||||||
for data in springs do
|
for data in springs do
|
||||||
local k, c,
|
local k, c,
|
||||||
|
|
@ -241,6 +257,8 @@ local function step_springs(dt: number)
|
||||||
data.x0_123, data.x1_123, data.v_123,
|
data.x0_123, data.x1_123, data.v_123,
|
||||||
data.x0_456, data.x1_456, data.v_456
|
data.x0_456, data.x1_456, data.v_456
|
||||||
|
|
||||||
|
if x0_123 == x1_123 and x0_456 == x1_456 then continue end
|
||||||
|
|
||||||
-- calculate displacement from target
|
-- calculate displacement from target
|
||||||
local dx_123 = x0_123 - x1_123
|
local dx_123 = x0_123 - x1_123
|
||||||
local dx_456 = x0_456 - x1_456
|
local dx_456 = x0_456 - x1_456
|
||||||
|
|
@ -261,9 +279,13 @@ local function step_springs(dt: number)
|
||||||
local v_123 = u_123 + dv_123
|
local v_123 = u_123 + dv_123
|
||||||
local v_456 = u_456 + dv_456
|
local v_456 = u_456 + dv_456
|
||||||
|
|
||||||
|
-- guarantee pos < pos + velocity <= goal
|
||||||
|
local a_123 = vector.max(get_min_vector_step(x0_123), vector.abs(v_123) * dt) * vector.sign(v_123)
|
||||||
|
local a_456 = vector.max(get_min_vector_step(x0_456), vector.abs(v_456) * dt) * vector.sign(v_456)
|
||||||
|
|
||||||
-- calculate new position
|
-- calculate new position
|
||||||
local x_123 = x0_123 + v_123*dt
|
local x_123 = x0_123 + a_123
|
||||||
local x_456 = x0_456 + v_456*dt
|
local x_456 = x0_456 + a_456
|
||||||
|
|
||||||
data.x0_123, data.x0_456 = x_123, x_456
|
data.x0_123, data.x0_456 = x_123, x_456
|
||||||
data.v_123, data.v_456 = v_123, v_456
|
data.v_123, data.v_456 = v_123, v_456
|
||||||
|
|
@ -272,21 +294,8 @@ end
|
||||||
|
|
||||||
local function update_spring_sources()
|
local function update_spring_sources()
|
||||||
for data, output in springs do
|
for data, output in springs do
|
||||||
local x0_123, x1_123, v_123,
|
local x0_123, x0_456 = data.x0_123, data.x0_456
|
||||||
x0_456, x1_456, v_456 =
|
if x0_123 == data.x1_123 and x0_456 == data.x1_456 then
|
||||||
data.x0_123, data.x1_123, data.v_123,
|
|
||||||
data.x0_456, data.x1_456, data.v_456
|
|
||||||
|
|
||||||
local max_difference = vector.max(
|
|
||||||
vector.abs(x0_123 - x1_123 :: any),
|
|
||||||
vector.abs(x0_456 - x1_456 :: any),
|
|
||||||
vector.abs(v_123 :: any),
|
|
||||||
vector.abs(v_456 :: any),
|
|
||||||
TOLERANCE_VECTOR
|
|
||||||
)
|
|
||||||
|
|
||||||
if max_difference == TOLERANCE_VECTOR then
|
|
||||||
-- close enough to target, unshedule spring and set value to target
|
|
||||||
springs[data] = nil
|
springs[data] = nil
|
||||||
output.cache = data.source_value
|
output.cache = data.source_value
|
||||||
else
|
else
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue