mirror of
https://github.com/1bardesign/batteries.git
synced 2024-11-25 23:24:35 +00:00
Merge branch 'feature/minmax-vector-ops-and-aabb-collisions'
This commit is contained in:
commit
0bc9ccb17b
@ -242,12 +242,40 @@ function intersect.aabb_point_overlap(pos, hs, v)
|
|||||||
return _apo_delta.x < hs.x and _apo_delta.y < hs.y
|
return _apo_delta.x < hs.x and _apo_delta.y < hs.y
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- discrete displacement
|
||||||
|
-- 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)
|
||||||
|
--separation between centres
|
||||||
|
_apo_delta_c
|
||||||
|
:vset(v)
|
||||||
|
:vsubi(pos)
|
||||||
|
--absolute separation
|
||||||
|
_apo_delta_c_abs
|
||||||
|
:vset(_apo_delta_c)
|
||||||
|
:absi()
|
||||||
|
if _apo_delta_c_abs.x < hs.x and _apo_delta_c_abs.y < hs.y then
|
||||||
|
return (into or vec2:zero())
|
||||||
|
--separating offset in both directions
|
||||||
|
:vset(hs)
|
||||||
|
:vsubi(_apo_delta_c_abs)
|
||||||
|
--minimum separating distance
|
||||||
|
:minori()
|
||||||
|
--in the right direction
|
||||||
|
:vmuli(_apo_delta_c:signi())
|
||||||
|
--from the aabb's point of view
|
||||||
|
:smuli(-1)
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
--return true on overlap, false otherwise
|
--return true on overlap, false otherwise
|
||||||
local _aao_abs_delta = vec2:zero()
|
local _aao_abs_delta = vec2:zero()
|
||||||
local _aao_total_size = vec2:zero()
|
local _aao_total_size = vec2:zero()
|
||||||
function intersect.aabb_aabb_overlap(pos, hs, opos, ohs)
|
function intersect.aabb_aabb_overlap(a_pos, a_hs, b_pos, b_hs)
|
||||||
_aao_abs_delta:vset(pos):vsubi(opos):absi()
|
_aao_abs_delta:vset(a_pos):vsubi(b_pos):absi()
|
||||||
_aao_total_size:vset(hs):vaddi(ohs)
|
_aao_total_size:vset(a_hs):vaddi(b_hs)
|
||||||
return _aao_abs_delta.x < _aao_total_size.x and _aao_abs_delta.y < _aao_total_size.y
|
return _aao_abs_delta.x < _aao_total_size.x and _aao_abs_delta.y < _aao_total_size.y
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -257,11 +285,11 @@ local _aac_delta = vec2:zero()
|
|||||||
local _aac_abs_delta = vec2:zero()
|
local _aac_abs_delta = vec2:zero()
|
||||||
local _aac_size = vec2:zero()
|
local _aac_size = vec2:zero()
|
||||||
local _aac_abs_amount = vec2:zero()
|
local _aac_abs_amount = vec2:zero()
|
||||||
function intersect.aabb_aabb_collide(apos, ahs, bpos, bhs, 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(apos):vsubi(bpos)
|
_aac_delta:vset(a_pos):vsubi(b_pos)
|
||||||
_aac_abs_delta:vset(_aac_delta):absi()
|
_aac_abs_delta:vset(_aac_delta):absi()
|
||||||
_aac_size:vset(ahs):vaddi(bhs)
|
_aac_size:vset(a_hs):vaddi(b_hs)
|
||||||
_aac_abs_amount:vset(_aac_size):vsubi(_aac_abs_delta)
|
_aac_abs_amount:vset(_aac_size):vsubi(_aac_abs_delta)
|
||||||
if _aac_abs_amount.x > COLLIDE_EPS and _aac_abs_amount.y > COLLIDE_EPS then
|
if _aac_abs_amount.x > COLLIDE_EPS and _aac_abs_amount.y > COLLIDE_EPS then
|
||||||
--actually collided
|
--actually collided
|
||||||
@ -287,8 +315,8 @@ end
|
|||||||
--return normal and fraction of dt encountered on collision, false otherwise
|
--return normal and fraction of dt encountered on collision, false otherwise
|
||||||
--TODO: re-pool storage here
|
--TODO: re-pool storage here
|
||||||
function intersect.aabb_aabb_collide_continuous(
|
function intersect.aabb_aabb_collide_continuous(
|
||||||
a_startpos, a_endpos, ahs,
|
a_startpos, a_endpos, a_hs,
|
||||||
b_startpos, b_endpos, bhs,
|
b_startpos, b_endpos, b_hs,
|
||||||
into
|
into
|
||||||
)
|
)
|
||||||
if not into then into = vec2:zero() end
|
if not into then into = vec2:zero() end
|
||||||
@ -301,11 +329,11 @@ function intersect.aabb_aabb_collide_continuous(
|
|||||||
do
|
do
|
||||||
local _self_half_delta = _self_delta_motion:smul(0.5)
|
local _self_half_delta = _self_delta_motion:smul(0.5)
|
||||||
local _self_bounds_pos = _self_half_delta:vadd(a_endpos)
|
local _self_bounds_pos = _self_half_delta:vadd(a_endpos)
|
||||||
local _self_bounds_hs = _self_half_delta:vadd(ahs)
|
local _self_bounds_hs = _self_half_delta:vadd(a_hs)
|
||||||
|
|
||||||
local _other_half_delta = _other_delta_motion:smul(0.5)
|
local _other_half_delta = _other_delta_motion:smul(0.5)
|
||||||
local _other_bounds_pos = _other_half_delta:vadd(b_endpos)
|
local _other_bounds_pos = _other_half_delta:vadd(b_endpos)
|
||||||
local _other_bounds_hs = _other_half_delta:vadd(bhs)
|
local _other_bounds_hs = _other_half_delta:vadd(b_hs)
|
||||||
|
|
||||||
if not body._overlap_raw(
|
if not body._overlap_raw(
|
||||||
_self_bounds_pos, _self_bounds_hs,
|
_self_bounds_pos, _self_bounds_hs,
|
||||||
@ -318,7 +346,7 @@ function intersect.aabb_aabb_collide_continuous(
|
|||||||
--get ccd minkowski box
|
--get ccd minkowski box
|
||||||
--this is a relative-space box
|
--this is a relative-space box
|
||||||
local _relative_delta_motion = _self_delta_motion:vsub(_other_delta_motion)
|
local _relative_delta_motion = _self_delta_motion:vsub(_other_delta_motion)
|
||||||
local _minkowski_halfsize = ahs:vadd(bhs)
|
local _minkowski_halfsize = a_hs:vadd(b_hs)
|
||||||
local _minkowski_pos = b_startpos:vsub(a_startpos)
|
local _minkowski_pos = b_startpos:vsub(a_startpos)
|
||||||
|
|
||||||
--if a line seg from our relative motion hits the minkowski box, we're in luck
|
--if a line seg from our relative motion hits the minkowski box, we're in luck
|
||||||
@ -407,6 +435,46 @@ function intersect.aabb_aabb_collide_continuous(
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- helper function to clamp point to aabb
|
||||||
|
function intersect.aabb_point_clamp(pos, hs, v, into)
|
||||||
|
local v_min = pos:pooled_copy():vsubi(hs)
|
||||||
|
local v_max = pos:pooled_copy():vaddi(hs)
|
||||||
|
into = into or vec2:zero()
|
||||||
|
into:vset(v):clampi(v_min, v_max)
|
||||||
|
vec2.release(v_min, v_max)
|
||||||
|
return into
|
||||||
|
end
|
||||||
|
|
||||||
|
-- return true on overlap, false otherwise
|
||||||
|
function intersect.aabb_circle_overlap(a_pos, a_hs, b_pos, b_rad)
|
||||||
|
local clamped = intersect.aabb_point_clamp(a_pos, a_hs, b_pos, vec2:pooled())
|
||||||
|
local edge_distance_squared = clamped:distance_squared(b_pos)
|
||||||
|
clamped:release()
|
||||||
|
return edge_distance_squared < (b_rad * b_rad)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- return msv on collision, false otherwise
|
||||||
|
function intersect.aabb_circle_collide(a_pos, a_hs, b_pos, b_rad, into)
|
||||||
|
local abs_delta = a_pos:pooled_copy():vsub(b_pos):absi()
|
||||||
|
--circle centre within aabb-like bounds, collide as an aabb
|
||||||
|
local like_aabb = abs_delta.x < a_hs.x or abs_delta.y < a_hs.y
|
||||||
|
--(clean up)
|
||||||
|
abs_delta:release()
|
||||||
|
--
|
||||||
|
local result
|
||||||
|
if like_aabb then
|
||||||
|
local pretend_hs = vec2:pooled():sset(b_rad)
|
||||||
|
result = intersect.aabb_aabb_collide(a_pos, a_hs, b_pos, pretend_hs, into)
|
||||||
|
pretend_hs:release()
|
||||||
|
else
|
||||||
|
--outside aabb-like bounds so we need to collide with the nearest clamped corner point
|
||||||
|
local clamped = intersect.aabb_point_clamp(a_pos, a_hs, b_pos, vec2:pooled())
|
||||||
|
result = intersect.circle_circle_collide(clamped, 0, b_pos, b_rad, into)
|
||||||
|
clamped:release()
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
--check if a point is in a polygon
|
--check if a point is in a polygon
|
||||||
--point is the point to test
|
--point is the point to test
|
||||||
--poly is a list of points in order
|
--poly is a list of points in order
|
||||||
|
57
vec2.lua
57
vec2.lua
@ -92,10 +92,13 @@ function vec2:pooled_copy()
|
|||||||
end
|
end
|
||||||
|
|
||||||
--release a vector to the pool
|
--release a vector to the pool
|
||||||
function vec2:release()
|
function vec2:release(...)
|
||||||
if vec2.pool_size() < _vec2_pool_limit then
|
if vec2.pool_size() < _vec2_pool_limit then
|
||||||
table.insert(_vec2_pool, self)
|
table.insert(_vec2_pool, self)
|
||||||
end
|
end
|
||||||
|
if ... then
|
||||||
|
vec2.release(...)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--unpack for multi-args
|
--unpack for multi-args
|
||||||
@ -448,6 +451,20 @@ function vec2:abs()
|
|||||||
return self:copy():absi()
|
return self:copy():absi()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------
|
||||||
|
-- sign
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
function vec2:signi()
|
||||||
|
self.x = math.sign(self.x)
|
||||||
|
self.y = math.sign(self.y)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
function vec2:sign()
|
||||||
|
return self:copy():signi()
|
||||||
|
end
|
||||||
|
|
||||||
-----------------------------------------------------------
|
-----------------------------------------------------------
|
||||||
-- truncation/rounding
|
-- truncation/rounding
|
||||||
-----------------------------------------------------------
|
-----------------------------------------------------------
|
||||||
@ -599,4 +616,42 @@ function vec2:apply_friction_xy(mu_x, mu_y, dt)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--minimum/maximum components
|
||||||
|
function vec2:mincomp()
|
||||||
|
return math.min(self.x, self.y)
|
||||||
|
end
|
||||||
|
|
||||||
|
function vec2:maxcomp()
|
||||||
|
return math.max(self.x, self.y)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- mask out min component, with preference to keep x
|
||||||
|
function vec2:majori()
|
||||||
|
if self.x > self.y then
|
||||||
|
self.y = 0
|
||||||
|
else
|
||||||
|
self.x = 0
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
-- mask out max component, with preference to keep x
|
||||||
|
function vec2:minori()
|
||||||
|
if self.x < self.y then
|
||||||
|
self.y = 0
|
||||||
|
else
|
||||||
|
self.x = 0
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--garbage generating versions
|
||||||
|
function vec2:major(axis)
|
||||||
|
return self:copy():majori(axis)
|
||||||
|
end
|
||||||
|
|
||||||
|
function vec2:minor(axis)
|
||||||
|
return self:copy():minori(axis)
|
||||||
|
end
|
||||||
|
|
||||||
return vec2
|
return vec2
|
||||||
|
Loading…
Reference in New Issue
Block a user