Reuse the simplex table

Always use the same simplex table
This commit is contained in:
Pablo Ariel Mayobre (Positive07) 2017-11-05 18:52:55 -03:00
parent 81676a95b0
commit 002fee0bd6

45
gjk.lua
View File

@ -28,17 +28,19 @@ local _PACKAGE = (...):match("^(.+)%.[^%.]+")
local vector = require(_PACKAGE .. '.vector-light') local vector = require(_PACKAGE .. '.vector-light')
local huge, abs = math.huge, math.abs local huge, abs = math.huge, math.abs
local simplex = {}
local function support(shape_a, shape_b, dx, dy) local function support(shape_a, shape_b, dx, dy)
local x,y = shape_a:support(dx,dy) local x,y = shape_a:support(dx,dy)
return vector.sub(x,y, shape_b:support(-dx, -dy)) return vector.sub(x,y, shape_b:support(-dx, -dy))
end end
-- returns closest edge to the origin -- returns closest edge to the origin
local function closest_edge(simplex) local function closest_edge(n)
local e = {dist = huge} local e = {dist = huge}
local i = #simplex-1 local i = n-1
for k = 1,#simplex-1,2 do for k = 1,n-1,2 do
local ax,ay = simplex[i], simplex[i+1] local ax,ay = simplex[i], simplex[i+1]
local bx,by = simplex[k], simplex[k+1] local bx,by = simplex[k], simplex[k+1]
i = k i = k
@ -57,7 +59,7 @@ local function closest_edge(simplex)
return e return e
end end
local function EPA(shape_a, shape_b, simplex) local function EPA(shape_a, shape_b)
-- make sure simplex is oriented counter clockwise -- make sure simplex is oriented counter clockwise
local cx,cy, bx,by, ax,ay = unpack(simplex) local cx,cy, bx,by, ax,ay = unpack(simplex)
if vector.dot(ax-bx,ay-by, cx-bx,cy-by) < 0 then if vector.dot(ax-bx,ay-by, cx-bx,cy-by) < 0 then
@ -67,9 +69,9 @@ local function EPA(shape_a, shape_b, simplex)
-- the expanding polytype algorithm -- the expanding polytype algorithm
local is_either_circle = shape_a._center or shape_b._center local is_either_circle = shape_a._center or shape_b._center
local last_diff_dist = huge local last_diff_dist, n = huge, 6
while true do while true do
local e = closest_edge(simplex) local e = closest_edge(n)
local px,py = support(shape_a, shape_b, e.nx, e.ny) local px,py = support(shape_a, shape_b, e.nx, e.ny)
local d = vector.dot(px,py, e.nx, e.ny) local d = vector.dot(px,py, e.nx, e.ny)
@ -82,13 +84,15 @@ local function EPA(shape_a, shape_b, simplex)
-- simplex = {..., simplex[e.i-1], px, py, simplex[e.i] -- simplex = {..., simplex[e.i-1], px, py, simplex[e.i]
table.insert(simplex, e.i, py) table.insert(simplex, e.i, py)
table.insert(simplex, e.i, px) table.insert(simplex, e.i, px)
n = n + 2
end end
end end
-- : : origin must be in plane between A and B -- : : origin must be in plane between A and B
-- B o------o A since A is the furthest point on the MD -- B o------o A since A is the furthest point on the MD
-- : : in direction of the origin. -- : : in direction of the origin.
local function do_line(simplex) local function do_line()
local bx,by, ax,ay = unpack(simplex) local bx,by, ax,ay = unpack(simplex)
local abx,aby = bx-ax, by-ay local abx,aby = bx-ax, by-ay
@ -98,7 +102,7 @@ local function do_line(simplex)
if vector.dot(dx,dy, -ax,-ay) < 0 then if vector.dot(dx,dy, -ax,-ay) < 0 then
dx,dy = -dx,-dy dx,dy = -dx,-dy
end end
return simplex, dx,dy return 4, dx,dy
end end
-- B .' -- B .'
@ -108,7 +112,7 @@ end
-- | _.-' '. from left of BC. -- | _.-' '. from left of BC.
-- o-' 3 -- o-' 3
-- C '. -- C '.
local function do_triangle(simplex) local function do_triangle()
local cx,cy, bx,by, ax,ay = unpack(simplex) local cx,cy, bx,by, ax,ay = unpack(simplex)
local aox,aoy = -ax,-ay local aox,aoy = -ax,-ay
local abx,aby = bx-ax, by-ay local abx,aby = bx-ax, by-ay
@ -124,7 +128,7 @@ local function do_triangle(simplex)
simplex[1], simplex[2] = bx,by simplex[1], simplex[2] = bx,by
simplex[3], simplex[4] = ax,ay simplex[3], simplex[4] = ax,ay
simplex[5], simplex[6] = nil, nil simplex[5], simplex[6] = nil, nil
return simplex, dx,dy return 4, dx,dy
end end
-- test region 3 -- test region 3
@ -136,11 +140,11 @@ local function do_triangle(simplex)
-- simplex = {cx,cy, ax,ay} -- simplex = {cx,cy, ax,ay}
simplex[3], simplex[4] = ax,ay simplex[3], simplex[4] = ax,ay
simplex[5], simplex[6] = nil, nil simplex[5], simplex[6] = nil, nil
return simplex, dx,dy return 4, dx,dy
end end
-- must be in region 4 -- must be in region 4
return simplex return 6
end end
local function GJK(shape_a, shape_b) local function GJK(shape_a, shape_b)
@ -158,8 +162,7 @@ local function GJK(shape_a, shape_b)
return false return false
end end
local simplex = {ax,ay} simplex[1], simplex[2] = ax, ay
local n = 2
local dx,dy = -ax,-ay local dx,dy = -ax,-ay
-- first iteration: line case -- first iteration: line case
@ -168,9 +171,10 @@ local function GJK(shape_a, shape_b)
return false return false
end end
simplex[n+1], simplex[n+2] = ax,ay simplex[3], simplex[4] = ax,ay
simplex, dx, dy = do_line(simplex, dx, dy) dx, dy = do_line()
n = 4
local n
-- all other iterations must be the triangle case -- all other iterations must be the triangle case
while true do while true do
@ -180,12 +184,11 @@ local function GJK(shape_a, shape_b)
return false return false
end end
simplex[n+1], simplex[n+2] = ax,ay simplex[5], simplex[6] = ax,ay
simplex, dx, dy = do_triangle(simplex, dx,dy) n, dx, dy = do_triangle()
n = #simplex
if n == 6 then if n == 6 then
return true, EPA(shape_a, shape_b, simplex) return true, EPA(shape_a, shape_b)
end end
end end
end end