More pooled storage for intersect.lua

This commit is contained in:
Max Cahill 2021-06-29 14:43:55 +10:00
parent 009beadc68
commit fe135c533b

View File

@ -9,8 +9,7 @@
continuous sweeps (where provided) also return the continuous sweeps (where provided) also return the
time-domain position of first intersection time-domain position of first intersection
TODO: refactor vector storage to be pooled rather than fully local TODO: refactor vector storage to be pooled where needed
so these functions can be reentrant
]] ]]
local path = (...):gsub("intersect", "") local path = (...):gsub("intersect", "")
@ -35,18 +34,18 @@ function intersect.circle_circle_overlap(a_pos, a_rad, b_pos, b_rad)
return a_pos:distance_squared(b_pos) < rad * rad return a_pos:distance_squared(b_pos) < rad * rad
end end
local _ccc_delta = vec2:zero()
function intersect.circle_circle_collide(a_pos, a_rad, b_pos, b_rad, into) function intersect.circle_circle_collide(a_pos, a_rad, b_pos, b_rad, into)
--get delta --get delta
_ccc_delta:vset(a_pos):vsubi(b_pos) local delta = a_pos:pooled_copy():vsubi(b_pos)
--squared threshold --squared threshold
local rad = a_rad + b_rad local rad = a_rad + b_rad
local dist = _ccc_delta:length_squared() local dist = delta:length_squared()
local res = false
if dist < rad * rad then if dist < rad * rad then
if dist == 0 then if dist == 0 then
--singular case; just resolve vertically --singular case; just resolve vertically
dist = 1 dist = 1
_ccc_delta:sset(0,1) delta:sset(0,1)
else else
--get actual distance --get actual distance
dist = math.sqrt(dist) dist = math.sqrt(dist)
@ -56,10 +55,10 @@ function intersect.circle_circle_collide(a_pos, a_rad, b_pos, b_rad, into)
into = vec2:zero() into = vec2:zero()
end end
--normalise, scale to separating distance --normalise, scale to separating distance
into:vset(_ccc_delta):sdivi(dist):smuli(rad - dist) res = into:vset(delta):sdivi(dist):smuli(rad - dist)
return into
end end
return false delta:release()
return res
end end
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@ -237,80 +236,66 @@ end
-- axis aligned bounding boxes -- axis aligned bounding boxes
--return true on overlap, false otherwise --return true on overlap, false otherwise
local _apo_delta = vec2:zero()
function intersect.aabb_point_overlap(pos, hs, v) function intersect.aabb_point_overlap(pos, hs, v)
_apo_delta:vset(pos):vsubi(v):absi() local delta = pos:pooled_copy():vsubi(v):absi()
return _apo_delta.x < hs.x and _apo_delta.y < hs.y local overlap = delta.x < hs.x and delta.y < hs.y
delta:release()
return overlap
end end
-- discrete displacement -- discrete displacement
-- return msv to push point to closest edge of aabb -- return msv to push point to closest edge of aabb
local _apo_delta_c = vec2:zero()
local _apo_delta_c_abs = vec2:zero()
function intersect.aabb_point_collide(pos, hs, v, into) function intersect.aabb_point_collide(pos, hs, v, into)
--separation between centres --separation between centres
_apo_delta_c local delta_c = v:pooled_copy():vsubi(pos)
:vset(v)
:vsubi(pos)
--absolute separation --absolute separation
_apo_delta_c_abs local delta_c_abs = delta_c:pooled_copy():absi()
:vset(_apo_delta_c) local res = false
:absi() if delta_c_abs.x < hs.x and delta_c_abs.y < hs.y then
if _apo_delta_c_abs.x < hs.x and _apo_delta_c_abs.y < hs.y then res = (into or vec2:zero())
return (into or vec2:zero())
--separating offset in both directions --separating offset in both directions
:vset(hs) :vset(hs)
:vsubi(_apo_delta_c_abs) :vsubi(delta_c_abs)
--minimum separating distance --minimum separating distance
:minori() :minori()
--in the right direction --in the right direction
:vmuli(_apo_delta_c:signi()) :vmuli(delta_c:signi())
--from the aabb's point of view --from the aabb's point of view
:smuli(-1) :smuli(-1)
end end
return false vec2.release(delta_c, delta_c_abs)
return res
end end
--return true on overlap, false otherwise --return true on overlap, false otherwise
local _aao_abs_delta = vec2:zero()
local _aao_total_size = vec2:zero()
function intersect.aabb_aabb_overlap(a_pos, a_hs, b_pos, b_hs) function intersect.aabb_aabb_overlap(a_pos, a_hs, b_pos, b_hs)
_aao_abs_delta:vset(a_pos):vsubi(b_pos):absi() local delta = a_pos:pooled_copy():vsubi(b_pos):absi()
_aao_total_size:vset(a_hs):vaddi(b_hs) local total_size = a_hs:pooled_copy():vaddi(b_hs)
return _aao_abs_delta.x < _aao_total_size.x and _aao_abs_delta.y < _aao_total_size.y local overlap = delta.x < total_size.x and delta.y < total_size.y
vec2.release(delta, total_size)
return overlap
end end
--discrete displacement --discrete displacement
--return msv on collision, false otherwise --return msv on collision, false otherwise
local _aac_delta = vec2:zero()
local _aac_abs_delta = vec2:zero()
local _aac_size = vec2:zero()
local _aac_abs_amount = vec2:zero()
function intersect.aabb_aabb_collide(a_pos, a_hs, b_pos, b_hs, into) function intersect.aabb_aabb_collide(a_pos, a_hs, b_pos, b_hs, into)
if not into then into = vec2:zero() end if not into then into = vec2:zero() end
_aac_delta:vset(a_pos):vsubi(b_pos) local delta = a_pos:pooled_copy():vsubi(b_pos)
_aac_abs_delta:vset(_aac_delta):absi() local abs_delta = delta:pooled_copy():absi()
_aac_size:vset(a_hs):vaddi(b_hs) local size = a_hs:pooled_copy():vaddi(b_hs)
_aac_abs_amount:vset(_aac_size):vsubi(_aac_abs_delta) local abs_amount = size:pooled_copy():vsubi(abs_delta)
if _aac_abs_amount.x > COLLIDE_EPS and _aac_abs_amount.y > COLLIDE_EPS then local res = false
if abs_amount.x > COLLIDE_EPS and abs_amount.y > COLLIDE_EPS then
--actually collided --actually collided
if _aac_abs_amount.x <= _aac_abs_amount.y then if abs_amount.x <= abs_amount.y then
--x min --x min
if _aac_delta.x < 0 then res = into:sset(abs_amount.x * math.sign(delta.x), 0)
return into:sset(-_aac_abs_amount.x, 0)
else
return into:sset(_aac_abs_amount.x, 0)
end
else else
--y min --y min
if _aac_delta.y < 0 then res = into:sset(0, abs_amount.y * math.sign(delta.y))
return into:sset(0, -_aac_abs_amount.y)
else
return into:sset(0, _aac_abs_amount.y)
end
end end
end end
return false return res
end end
--return normal and fraction of dt encountered on collision, false otherwise --return normal and fraction of dt encountered on collision, false otherwise