From 002fee0bd61c58b7b0b50db73e970dabf1faaf8c Mon Sep 17 00:00:00 2001 From: "Pablo Ariel Mayobre (Positive07)" Date: Sun, 5 Nov 2017 18:52:55 -0300 Subject: [PATCH 1/5] Reuse the simplex table Always use the same simplex table --- gjk.lua | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/gjk.lua b/gjk.lua index ebaad05..83b3f35 100644 --- a/gjk.lua +++ b/gjk.lua @@ -28,17 +28,19 @@ local _PACKAGE = (...):match("^(.+)%.[^%.]+") local vector = require(_PACKAGE .. '.vector-light') local huge, abs = math.huge, math.abs +local simplex = {} + local function support(shape_a, shape_b, dx, dy) local x,y = shape_a:support(dx,dy) return vector.sub(x,y, shape_b:support(-dx, -dy)) end -- returns closest edge to the origin -local function closest_edge(simplex) +local function closest_edge(n) local e = {dist = huge} - local i = #simplex-1 - for k = 1,#simplex-1,2 do + local i = n-1 + for k = 1,n-1,2 do local ax,ay = simplex[i], simplex[i+1] local bx,by = simplex[k], simplex[k+1] i = k @@ -57,7 +59,7 @@ local function closest_edge(simplex) return e end -local function EPA(shape_a, shape_b, simplex) +local function EPA(shape_a, shape_b) -- make sure simplex is oriented counter clockwise local cx,cy, bx,by, ax,ay = unpack(simplex) 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 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 - local e = closest_edge(simplex) + local e = closest_edge(n) local px,py = support(shape_a, shape_b, 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] table.insert(simplex, e.i, py) table.insert(simplex, e.i, px) + + n = n + 2 end end -- : : origin must be in plane between A and B -- B o------o A since A is the furthest point on the MD -- : : in direction of the origin. -local function do_line(simplex) +local function do_line() local bx,by, ax,ay = unpack(simplex) 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 dx,dy = -dx,-dy end - return simplex, dx,dy + return 4, dx,dy end -- B .' @@ -108,7 +112,7 @@ end -- | _.-' '. from left of BC. -- o-' 3 -- C '. -local function do_triangle(simplex) +local function do_triangle() local cx,cy, bx,by, ax,ay = unpack(simplex) local aox,aoy = -ax,-ay local abx,aby = bx-ax, by-ay @@ -124,7 +128,7 @@ local function do_triangle(simplex) simplex[1], simplex[2] = bx,by simplex[3], simplex[4] = ax,ay simplex[5], simplex[6] = nil, nil - return simplex, dx,dy + return 4, dx,dy end -- test region 3 @@ -136,11 +140,11 @@ local function do_triangle(simplex) -- simplex = {cx,cy, ax,ay} simplex[3], simplex[4] = ax,ay simplex[5], simplex[6] = nil, nil - return simplex, dx,dy + return 4, dx,dy end -- must be in region 4 - return simplex + return 6 end local function GJK(shape_a, shape_b) @@ -158,8 +162,7 @@ local function GJK(shape_a, shape_b) return false end - local simplex = {ax,ay} - local n = 2 + simplex[1], simplex[2] = ax, ay local dx,dy = -ax,-ay -- first iteration: line case @@ -168,9 +171,10 @@ local function GJK(shape_a, shape_b) return false end - simplex[n+1], simplex[n+2] = ax,ay - simplex, dx, dy = do_line(simplex, dx, dy) - n = 4 + simplex[3], simplex[4] = ax,ay + dx, dy = do_line() + + local n -- all other iterations must be the triangle case while true do @@ -180,12 +184,11 @@ local function GJK(shape_a, shape_b) return false end - simplex[n+1], simplex[n+2] = ax,ay - simplex, dx, dy = do_triangle(simplex, dx,dy) - n = #simplex + simplex[5], simplex[6] = ax,ay + n, dx, dy = do_triangle() if n == 6 then - return true, EPA(shape_a, shape_b, simplex) + return true, EPA(shape_a, shape_b) end end end From 0645bae6a9f44985e071dcc168958cde4e93abdc Mon Sep 17 00:00:00 2001 From: "Pablo Ariel Mayobre (Positive07)" Date: Sun, 5 Nov 2017 19:07:57 -0300 Subject: [PATCH 2/5] Reuse the edge table in closest_edge Avoid unnecessary allocations of tables --- gjk.lua | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/gjk.lua b/gjk.lua index 83b3f35..4949317 100644 --- a/gjk.lua +++ b/gjk.lua @@ -36,8 +36,9 @@ local function support(shape_a, shape_b, dx, dy) end -- returns closest edge to the origin +local edge = {} local function closest_edge(n) - local e = {dist = huge} + edge.dist = huge local i = n-1 for k = 1,n-1,2 do @@ -49,14 +50,14 @@ local function closest_edge(n) local nx,ny = vector.normalize(ex,ey) local d = vector.dot(ax,ay, nx,ny) - if d < e.dist then - e.dist = d - e.nx, e.ny = nx, ny - e.i = k + if d < edge.dist then + edge.dist = d + edge.nx, edge.ny = nx, ny + edge.i = k end end - return e + return edge end local function EPA(shape_a, shape_b) From 14aa6450b96cf5b148bbc3cf11b98fd99ff17e36 Mon Sep 17 00:00:00 2001 From: "Pablo Ariel Mayobre (Positive07)" Date: Sun, 5 Nov 2017 19:14:37 -0300 Subject: [PATCH 3/5] Use a for loop instead of table.insert To increase performance (by @pfirsich) --- gjk.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/gjk.lua b/gjk.lua index 4949317..cd49bf4 100644 --- a/gjk.lua +++ b/gjk.lua @@ -83,9 +83,11 @@ local function EPA(shape_a, shape_b) last_diff_dist = diff_dist -- simplex = {..., simplex[e.i-1], px, py, simplex[e.i] - table.insert(simplex, e.i, py) - table.insert(simplex, e.i, px) - + for i = n, e.i, -1 do + simplex[i+2] = simplex[i] + end + simplex[e.i+0] = px + simplex[e.i+1] = py n = n + 2 end end From 1bee6093e6481ea8974f5fcbd58d95de3270f820 Mon Sep 17 00:00:00 2001 From: "Pablo Ariel Mayobre (Positive07)" Date: Sun, 5 Nov 2017 19:38:18 -0300 Subject: [PATCH 4/5] Fixed error in do_line Add start and end arguments to unpack --- gjk.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gjk.lua b/gjk.lua index cd49bf4..2686033 100644 --- a/gjk.lua +++ b/gjk.lua @@ -62,7 +62,7 @@ end local function EPA(shape_a, shape_b) -- 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, 1, 6) if vector.dot(ax-bx,ay-by, cx-bx,cy-by) < 0 then simplex[1],simplex[2] = ax,ay simplex[5],simplex[6] = cx,cy @@ -96,7 +96,7 @@ end -- B o------o A since A is the furthest point on the MD -- : : in direction of the origin. local function do_line() - local bx,by, ax,ay = unpack(simplex) + local bx,by, ax,ay = unpack(simplex, 1, 4) local abx,aby = bx-ax, by-ay @@ -105,7 +105,7 @@ local function do_line() if vector.dot(dx,dy, -ax,-ay) < 0 then dx,dy = -dx,-dy end - return 4, dx,dy + return dx,dy end -- B .' @@ -116,7 +116,7 @@ end -- o-' 3 -- C '. local function do_triangle() - local cx,cy, bx,by, ax,ay = unpack(simplex) + local cx,cy, bx,by, ax,ay = unpack(simplex, 1, 6) local aox,aoy = -ax,-ay local abx,aby = bx-ax, by-ay local acx,acy = cx-ax, cy-ay From 93fa0694740b5632854b184a3fbd12da16b760fc Mon Sep 17 00:00:00 2001 From: "Pablo Ariel Mayobre (Positive07)" Date: Sun, 5 Nov 2017 19:46:31 -0300 Subject: [PATCH 5/5] Removed unnecessary statements --- gjk.lua | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/gjk.lua b/gjk.lua index 2686033..e792f19 100644 --- a/gjk.lua +++ b/gjk.lua @@ -28,7 +28,7 @@ local _PACKAGE = (...):match("^(.+)%.[^%.]+") local vector = require(_PACKAGE .. '.vector-light') local huge, abs = math.huge, math.abs -local simplex = {} +local simplex, edge = {}, {} local function support(shape_a, shape_b, dx, dy) local x,y = shape_a:support(dx,dy) @@ -36,7 +36,6 @@ local function support(shape_a, shape_b, dx, dy) end -- returns closest edge to the origin -local edge = {} local function closest_edge(n) edge.dist = huge @@ -56,8 +55,6 @@ local function closest_edge(n) edge.i = k end end - - return edge end local function EPA(shape_a, shape_b) @@ -72,22 +69,22 @@ local function EPA(shape_a, shape_b) local is_either_circle = shape_a._center or shape_b._center local last_diff_dist, n = huge, 6 while true do - local e = closest_edge(n) - local px,py = support(shape_a, shape_b, e.nx, e.ny) - local d = vector.dot(px,py, e.nx, e.ny) + closest_edge(n) + local px,py = support(shape_a, shape_b, edge.nx, edge.ny) + local d = vector.dot(px,py, edge.nx, edge.ny) - local diff_dist = d - e.dist + local diff_dist = d - edge.dist if diff_dist < 1e-6 or (is_either_circle and abs(last_diff_dist - diff_dist) < 1e-10) then - return -d*e.nx, -d*e.ny + return -d*edge.nx, -d*edge.ny end last_diff_dist = diff_dist - -- simplex = {..., simplex[e.i-1], px, py, simplex[e.i] - for i = n, e.i, -1 do + -- simplex = {..., simplex[edge.i-1], px, py, simplex[edge.i] + for i = n, edge.i, -1 do simplex[i+2] = simplex[i] end - simplex[e.i+0] = px - simplex[e.i+1] = py + simplex[edge.i+0] = px + simplex[edge.i+1] = py n = n + 2 end end @@ -130,7 +127,6 @@ local function do_triangle() -- simplex = {bx,by, ax,ay} simplex[1], simplex[2] = bx,by simplex[3], simplex[4] = ax,ay - simplex[5], simplex[6] = nil, nil return 4, dx,dy end @@ -142,7 +138,6 @@ local function do_triangle() if vector.dot(dx,dy, aox, aoy) > 0 then -- simplex = {cx,cy, ax,ay} simplex[3], simplex[4] = ax,ay - simplex[5], simplex[6] = nil, nil return 4, dx,dy end