#### Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

# My 2D physics aabb testing seems a little flooey

in Bugs Posts: 1,379

Attached is a project I made on top of PhysicsLab to better understand raycasting and aabb queries.

It’s pretty simple and self-explanatory, but if you play with it for any length of time, you’ll probably notice the bug: the purple square seems to be detecting the blue line when they aren’t touching at all.

In the attached screenshot you can see this happening: the purple text reports that the query has detected the line, but they’re not touching—I’ve racked my brain on this one, can anybody help?

Tagged:

• Posts: 9,584

@UberGoober The problem with trying to figure out what’s wrong is first trying to figure out what code is actually being run. Then trying to jump around from tab to tab to see what to look for. You’re adding code to an existing project that in my opinion is hard to follow to begin with since there’s 7 different examples all reusing some different code here and there. Whenever I have a problem with something not working, I’ll create another project with as little code as possible and work with that until I figure out what’s wrong. Since you added code, take what you added and create another project with that and see how raycast and aabb works, or in your case, doesn’t.

• Posts: 1,125

+1 on small test code.

• Posts: 9,584

@UberGoober Slide your finger to move the left square to the circle or the other square. The moving square is the aabb area. Below are some things you’ll see.

1.) rect to rect. They don’t have to touch to cause a hit.
2.) rect to circle. They don’t have to touch and the hit area around the circle appears to be a square the size of the circle.

``````viewer.mode=FULLSCREEN

function setup()
rectMode(CENTER)
stroke(255)
strokeWidth(2)

s1=physics.body(CIRCLE,60)
s1.x=WIDTH/2
s1.y=HEIGHT/2+200
s1.type=STATIC

r1=physics.body(POLYGON,vec2(-40,40),vec2(-40,-40),vec2(40,-40),vec2(40,40))
r1.x=WIDTH/2
r1.y=300
r1.type=STATIC

tx,ty=WIDTH/2-300,HEIGHT-300
end

function draw()
background()

noFill()
rect(r1.x,r1.y,80,80)
ellipse(s1.x,s1.y,120)

q=physics.queryAABB(vec2(tx-40,ty-40),vec2(tx+40,ty+40))
if #q~=0 then
fill(0,255,0)
end

rect(tx,ty,80,80)
end

function touched(t)
if t.state==BEGAN or t.state==CHANGED then
tx=t.x
ty=t.y+150
end
end
``````
• edited September 27 Posts: 1,379
@dave1707 what a great little demo you whipped up—I was here deleting all the extraneous tabs in my existing project and arguing with myself about which lines of code should stay or not.

So yeah it looks like you done zeroed in on a bug—the 2D physics engine’s aabb routines seem to be yielding the wrong results.

@Simeon, did we find something new here?
• Posts: 9,584

@UberGoober I wouldn’t say they’re the wrong results, just not as exact as they could be. As far as I know, that might be the way it’s written, close enough to get the job done. If you’re running a game at full speed that’s using aabb to check something, you might not even notice the difference.

• Posts: 1,379

@dave1707 ennnnnnnnnnnh I think if a piece of software is going to tell me it made me a circle, that thing should act like a circle.

• Posts: 9,584

@UberGoober Its possible they were trying to keep the code for aabb small. Try writing some code that will indicate when any part of a rectangle of any size touches any part of a circle of any size.

• edited September 28 Posts: 1,379
@dave1707 I have had a lifetime’s worth of experience being wrong about things, so I’m sure this could be yet another one, but I find it hard to believe that a codebase that can accurately calculate a ball rolling down a slope doesn’t already have all the code it needs to accurately detect a circle overlapping a square.

I’ll be flabbergasted if it’s not a bug.
• edited September 28 Posts: 9,584

@UberGoober You may be right, but I’m sure that codes been around for a long time. I’d be surprised if no one found it in all that time.

PS. I checked up on aabb and it’s bounding volumes. It’s not meant to be exact, but a quick check to see if two objects might be overlapping. If they pass the aabb check then if a more exact check needs to be done, it can be. If they don’t pass the simple aabb check, then there’s no need to do the more intensive calculation.

So it’s not a bug, but just a simple check. I didn’t know that, so thanks.

• Posts: 1,379
Huh, I guess that’s another log on the “things I was wrong about” fire!

I am, as the kids on my playground used to say, moded.

From my own brief googling it seems like there’s kind of a grid underlying everything in the physics 2D system—it’s not that simple, I gather, but for the sake of illustration, we could say that aabb querying isn’t telling you exactly where a shape is, it’s telling you if any part of the shape is in the same square of the grid.
• Posts: 1,379
@dave1707 I think it’s even more complex than that—according to this:

https://stackoverflow.com/questions/18689451/what-is-aabb-explanation-required

…aabb bounding boxes can also include **a body’s recent motions**!

…man, I wonder if there’s some way to actually render all aabb boxes for any given moment on screen.
• Posts: 9,584

@UberGoober Here’s another example showing that the bounding area is a square around the triangle. Move the triangle around the square and make contact. I’ll have to try another example to see if the motion is also included.

``````viewer.mode=STANDARD

function setup()
rectMode(CENTER)
stroke(255)
strokeWidth(2)
physics.gravity(0,0)
r1=physics.body(POLYGON,vec2(0,0),vec2(100,0),vec2(100,100))
r1.x=WIDTH/2
r1.y=100
r1.type=DYNAMIC
end

function draw()
background(0)
noFill()
line(r1.x,r1.y,r1.x+100,r1.y)
line(r1.x+100,r1.y,r1.x+100,r1.y+100)
line(r1.x,r1.y,r1.x+100,r1.y+100)
q=physics.queryAABB(vec2(WIDTH//2-50,HEIGHT//2-50),vec2(WIDTH//2+50,HEIGHT//2+50))
if #q~=0 then
fill(0,255,0)
end
rect(WIDTH/2,HEIGHT/2,100,100)
end

function touched(t)
if t.state==BEGAN or t.state==CHANGED then
r1.x=t.x-50
r1.y=t.y+150
end
end
``````
• Posts: 9,584

@UberGoober Here’s an example showing the trailing bounding area. There’s a fix circle shown and another circle off screen that’s falling. You have to wait about 8 seconds for the falling circle to hit the fixed circle. After the collision, move the aabb square above the circles and move it down. The aabb area will turn green well above the top circle. I’m not sure how the size of the trailing area is calculated. It has something to do with the speed of the moving object. If you remove the *10 so it doesn’t fall as far, the trailing area isn’t as much.

``````viewer.mode=FULLSCREEN

function setup()
rectMode(CENTER)
stroke(255)
strokeWidth(2)

s1=physics.body(CIRCLE,60)
s1.x=WIDTH/2
s1.y=HEIGHT*10
s1.type=DYNAMIC

s2=physics.body(CIRCLE,60)
s2.x=WIDTH/2
s2.y=100
s2.type=STATIC

tx,ty=WIDTH/2-300,HEIGHT-300
end

function draw()
background()
noFill()
ellipse(s1.x,s1.y,120)
ellipse(s2.x,s2.y,120)
q=physics.queryAABB(vec2(tx-40,ty-40),vec2(tx+40,ty+40))
if #q~=0 then
fill(0,255,0)
end
rect(tx,ty,80,80)
end

function touched(t)
if t.state==BEGAN or t.state==CHANGED then
tx=t.x
ty=t.y-150
end
end
``````
• Posts: 1,379

Nice demonstration!

I've been trying to figure out if there's a way to detect a body's actual aabb value at any moment in time.

In box2d (2.4.1 at least) bodies have a command "GetFixtureList", and whatever a 'fixture' is, it has a "GetAABB" command that returns the actual AABB being tracked by the physics simulation.

It looks like 'fixtures' are a component of Box2D that's intentionally obscured by Codea--I think fixtures allow a body to contain sub-bodies, and I am assuming @John decided that was an unnecessary layer of complexity for Codea, and in my opinion I think that's the right call in general.

• Posts: 1,379

…contains code that claims to output a pretty comprehensive survey of functions available at the global level, I think.

It’s written in lua, for a version of lua running on C#, though, and I can’t get it to do anything.

• Posts: 9,584

@UberGoober I don’t see any reason to know the aabb area. The whole purpose of aabb is just a quick check to see if two objects might be collideing. If aabb is true, then a more complex calculation can be don’t if the objects aren’t simple rectangles and you want to know exact collisions. In simple games, the aabb check might be enough, but in the physics code, you already have a collision function.

• Posts: 1,379

There are many reasons I’d like to know it — frankly, it’s honestly surprising to me that you don’t — but the simplest is that not knowing it created this whole post.

Isn’t that enough?

• edited September 28 Posts: 9,584

@UberGoober I guess I know more about aabb now then I did before, so in that respect it’s good. But as for using it, that doesn’t change much other than writing a few examples that uses it.

• Posts: 1,379

Right now, or should I say over the last few weeks, I've been trying to make a better demo of aabb and raycasting than the one in the current PhysicsLab--from which, currently, none of this is obvious or even, really, possible to guess.

I think being able to show people what's happening by visually representing the actual aabb boundaries would be fantastic.

And I think it would save other people a huge amount of frustration if right from the start they knew not to use aabb testing if you want results that are precise or--for goodness' sakes--current.

• Posts: 9,584

@UberGoober I think you’re missing the point of aabb. It’s not supposed to be used for precise or current collision results. It’s a quick and easy way (code wise) to check if 2 objects are colliding. If the 2 bounding areas don’t overlap, then the 2 objects in those areas aren’t colliding. If the bounding areas do overlap, then you can either say that’s close enough, or do a more intense (code wise) calculation to determine if they collide. It’s very simple code to determine if 2 rectangles overlap, so that would be very fast when checking a lot.

• Posts: 1,379

@dave1707 I think you’re missing the point of me missing the point. If I understand you correctly, you think I want aabb testing to be something it’s not, and that’s what I may have failed to make clear: I’m just trying to make an accurate demo.

I’m looking for a way to easily and accurately and visually demonstrate it to others, because the current PhysicsLab doesn’t.

• Posts: 1,379

Also I apologize @dave1707 for being a jerko earlier about circles being circles and stuff. You’d think I’d eaten enough humble pie in my life to not act that way anymore, and I try not to, but clearly I fail now and then. Sorry.

• Posts: 9,584

@UberGoober No need to apologize about anything. Most of the time I don’t understand what is being asked and I go off in the wrong direction.

• Posts: 1,379

Glad to hear it, @dave1707, thanks for letting me know.

For what it’s worth, in actual Box2D, you can query a body directly for its precise current aabb boundary, so wanting and using that information is at least common enough that they built it right into the API.

If you want to take a second to try to think of a way to clearly and visually demonstrate this unusual aspect of aabb querying without actually showing the boundaries themselves, I’d love to know what occurs to you.

• edited September 29 Posts: 9,584

@UberGoober I don’t think there’s an option in Codea to show it. If the aabb area is stationary, then it just the defined rectangle around it. If it’s a moving aabb, then it’s harder to pinpoint the area.

PS. Haven’t found a way to highlight the aabb area of a moving object.

• Posts: 1,379

@dave1707 maybe play around with this:

``````viewer.mode=OVERLAY

function boundsOf(body)
local ll, ur = body.position, body.position
if body.shapeType == CIRCLE then
else
for _, thisPoint in ipairs(body.points) do
local worldPoint = body:getWorldPoint(thisPoint)
if worldPoint.x < ll.x then ll.x = worldPoint.x end
if worldPoint.y < ll.y then ll.y = worldPoint.y end
if worldPoint.x > ur.x then ur.x = worldPoint.x end
if worldPoint.y > ur.y then ur.y = worldPoint.y end
end
end
return ll, ur
end

function tableHas(targetTable, candidate)
if not targetTable or not candidate then return end
for key, element in pairs(targetTable) do
if element == candidate then return key end
end
end

function setup()

rectMode(CENTER)
noStroke()
physics.gravity(vec2(0,0))

s1=physics.body(CIRCLE,60)
s1.x=WIDTH/2
s1.y=HEIGHT/2+200
s1.type=STATIC

r1=physics.body(POLYGON,vec2(-40,40),vec2(-40,-40),vec2(40,-40),vec2(40,40))
r1.x=WIDTH/2
r1.y=300

tx,ty=WIDTH/2-300,HEIGHT-300

r2=physics.body(POLYGON,vec2(-40,40),vec2(-40,-40),vec2(40,-40),vec2(40,40))
r2.x=tx
r2.y=ty

end

function drawAABB()
local all = physics.queryAABB(vec2(0,0),vec2(WIDTH, HEIGHT))
for _, body in ipairs(all) do
local ll, ur = boundsOf(body)
if ll and ur then
local foundUpper, foundLower, foundRight, foundLeft, foundBounds
local yUp, yDown, xLeft, xRight = 0, 0, 0, 0
local bodiesAbove = physics.queryAABB(vec2(ll.x, ur.y + yUp), vec2(ur.x, ur.y + yUp + 1))
local indexOfBody = tableHas(bodiesAbove, body)
if bodiesAbove[indexOfBody] then
yUp = yUp + 1
else
foundUpper = true
end
end
local bodiesBelow = physics.queryAABB(vec2(ll.x, ll.y - (yDown + 1)), vec2(ur.x, ll.y - yDown))
local indexOfBody = tableHas(bodiesBelow, body)
if bodiesBelow[indexOfBody] then
yDown = yDown + 1
else
foundLower = true
end
end
local bodiesRight = physics.queryAABB(vec2(ur.x + xRight, ll.y), vec2(ur.x + xRight + 1, ur.y))
local indexOfBody = tableHas(bodiesRight, body)
if bodiesRight[indexOfBody] then
xRight = xRight + 1
else
foundRight = true
end
end
local bodiesLeft = physics.queryAABB(vec2(ll.x - (xLeft + 1), ll.y), vec2(ll.x - xLeft, ur.y))
local indexOfBody = tableHas(bodiesLeft, body)
if bodiesLeft[indexOfBody] then
xLeft = xLeft + 1
else
foundLeft = true
end
end

ur.x = ur.x + xRight
ur.y = ur.y + yUp

ll.x = ll.x - xLeft
ll.y = ll.y - yDown

foundBounds = true
end
pushStyle()
rectMode(CORNER)
fill(0)
rect(ll.x, ll.y, ur.x - ll.x, ur.y - ll.y)
popStyle()
end
end
end

function draw()
background(233, 218, 80)

drawAABB()

fill(233, 218, 80)
rect(r1.x,r1.y,80,80)
ellipse(s1.x,s1.y,120)
rect(r2.x,r2.y,80,80)

q=physics.queryAABB(vec2(tx-40,ty-40),vec2(tx+40,ty+40))
if #q > 1 then
fill(0,255,0)
end

rect(tx,ty,80,80)

end

function touched(t)
if t.state==BEGAN or t.state==CHANGED then
tx=t.x
ty=t.y+150
r2.position = vec2(tx, ty)
end
end

``````

…I think it draws the actual aabb, though it’s all brute-force. There might be a better way to do it.

The bodies are drawn in yellow and the aabbs are drawn as black boxes behind them.

I’m not sure if any single body’s aabb can be a shape other than a rectangle, if so this is imprecise because it only draws rectangles.

• Posts: 1,379

…and my original intersection lab project with accurate aabbs drawn (attached)

• Posts: 9,584

@UberGoober I don’t think this is working. There’s no reason the aabb area should increase in size just because I touch one of the other objects with the other.

• Posts: 1,379

@dave1707 it might not be working, but according to what I’ve read, there’s totally a reason the aabb would increase in size because of a touch.

Again, my code could be wrong, but as I understand it, aabb shows where an object could be, because it’s intended to return extremely best-guess results, leaving it up to other querying techniques to get more precise if needed.

So my code may not accurately reflect the aabb areas involved, but the concept that a given contact between two bodies results in a range of possibilities, therefore creating a larger black square, makes sense to me.

• Posts: 1,379

Also, if you run the intersection lab, the same code seems to give very accurate aabb results…

• Posts: 1,379

Also you’ll note that the faster you move the square into the circle’s space the larger the black box becomes.

That seems consistent.

• Posts: 9,584

@UberGoober I don’t think so. I’m barely moving the square into the circle and the black area increases in size as I move the square. Also, it only sometimes does it after I run the square into the other square and then into the circle. It should do it consistently if that’s how it works. I can agree that the faster you move the object, the more the aabb area will be behind the object. I would say that’s caused by the lag in calculating the aabb area and the position of the object. The aabb area is calculated where the object used to be. The only problem with trying to verify that, is the object is moving too fast to do anything to check it. The aabb area is calculated with the lower left and upper right x,y values. Those remain the same relative to the moving object, so I can’t see how the bounding area is going to change for the object.

• Posts: 1,379
@dave1707 I’m not sure if you’re getting, or if you’re getting and rejecting, the concept that aabb incorporates movement.

It’s not lag, it’s intentional, that’s how it’s supposed to work, at least as far as that SO article I linked to.
• Posts: 9,584

@UberGoober From what I’ve found so far, aabb will alter it size ( recalculate it’s area in the direction it’s moving ) to account for fast moving objects. It will also alter its position after a collision to reposition the object so fast moving objects aren’t overlapping each other at collision. So the increased bounding area will be in front or behind the moving object depending on what’s happening. I haven’t found any info about the bounding area increasing in size to each side. In your example, I was barely moving the square into the circle and the black area was increasing in size all around the square. That’s what I don’t think should be happening.

• edited October 3 Posts: 1,379
@dave1707 that makes sense

Have any idea why the objects only sometimes collide??
• Posts: 1,379

@dave1707 i just realized, one thing that could account for a larger box from even a small touch is the potential for rotation. If aabb queries take into account potential rotation as well as potential motion then even a small contact could create a larger box.

• Posts: 1,379

@dave1707 I think that hunch turned out to be at least partially correct.

I added a proper physics body drawer from PhysicsLab, so we can see what’s actually going on, and while it doesn’t fully explain the size of the boxes, it seems clear that box size expansion is linked to body rotation.

``````viewer.mode=OVERLAY

function boundsOf(body)
local ll, ur = body.position, body.position
if body.shapeType == CIRCLE then
else
for _, thisPoint in ipairs(body.points) do
local worldPoint = body:getWorldPoint(thisPoint)
if worldPoint.x <= ll.x then ll.x = worldPoint.x end
if worldPoint.y <= ll.y then ll.y = worldPoint.y end
if worldPoint.x >= ur.x then ur.x = worldPoint.x end
if worldPoint.y >= ur.y then ur.y = worldPoint.y end
end
end
return ll, ur
end

function tableHas(targetTable, candidate)
if not targetTable or not candidate then return end
for key, element in pairs(targetTable) do
if element == candidate then return key end
end
end

function setup()

rectMode(CENTER)
stroke(74)
strokeWidth(2)
physics.gravity(vec2(0,0))

s1=physics.body(CIRCLE,60)
s1.x=WIDTH/2
s1.y=HEIGHT/2+200
s1.type=STATIC

r1=physics.body(POLYGON,vec2(-40,40),vec2(-40,-40),vec2(40,-40),vec2(40,40))
r1.x=WIDTH/2
r1.y=300

tx,ty=WIDTH/2-300,HEIGHT-300

r2=physics.body(POLYGON,vec2(-40,40),vec2(-40,-40),vec2(40,-40),vec2(40,40))
r2.x=tx
r2.y=ty

end

function drawAABB()
local all = physics.queryAABB(vec2(0,0),vec2(WIDTH, HEIGHT))
for _, body in ipairs(all) do
local ll, ur = boundsOf(body)
if ll and ur then
local foundUpper, foundLower, foundRight, foundLeft, foundBounds
local yUp, yDown, xLeft, xRight = 0, 0, 0, 0
--find left edge
local bodiesToLeft = physics.queryAABB(vec2(0,0), vec2(ll.x - xLeft, HEIGHT))
if tableHas(bodiesToLeft, body) then
xLeft = xLeft + 1
else
xLeft = xLeft - 1
foundLeft = true
end
end
--find right edge
local bodiesToRight = physics.queryAABB(vec2(ur.x + xRight, 0), vec2(WIDTH, HEIGHT))
if tableHas(bodiesToRight, body) then
xRight = xRight + 1
else
xRight = xRight - 1
foundRight = true
end
end
--find top
local bodiesAbove = physics.queryAABB(vec2(0, ur.y + yUp), vec2(WIDTH, HEIGHT))
if tableHas(bodiesAbove, body) then
yUp = yUp + 1
else
yUp = yUp - 1
foundUpper = true
end
end
--find bottom
local bodiesBelow = physics.queryAABB(vec2(0, 0), vec2(WIDTH, ll.y - yDown))
if tableHas(bodiesBelow, body) then
yDown = yDown + 1
else
yDown = yDown - 1
foundLower = true
end
end

ur.x = ur.x + xRight
ur.y = ur.y + yUp

ll.x = ll.x - xLeft
ll.y = ll.y - yDown

foundBounds = true
end
pushStyle()
rectMode(CORNER)
fill(0)
rect(ll.x, ll.y, ur.x - ll.x, ur.y - ll.y)
popStyle()
end
end
end

function draw()
background(233, 218, 80)

drawAABB()

q=physics.queryAABB(vec2(tx-40,ty-40),vec2(tx+40,ty+40))
if #q > 1 then
fill(0,255,0)
end

bodiesDraw({r1, r2, s1})
end

function touched(t)
if t.state==BEGAN or t.state==CHANGED then
tx=t.x
ty=t.y+150
r2.position = vec2(tx, ty)
end
end

function bodiesDraw(bodies)
for i,body in ipairs(bodies) do
pushMatrix()
translate(body.x, body.y)
rotate(body.angle)

if body.type == STATIC then
stroke(255,255,255,255)
elseif body.type == DYNAMIC then
stroke(150,255,150,255)
elseif body.type == KINEMATIC then
stroke(150,150,255,255)
end

if body.shapeType == POLYGON then
strokeWidth(3.0)
local points = body.points
for j = 1,#points do
a = points[j]
b = points[(j % #points)+1]
line(a.x, a.y, b.x, b.y)
end
elseif body.shapeType == CHAIN or body.shapeType == EDGE then
strokeWidth(3.0)
local points = body.points
for j = 1,#points-1 do
a = points[j]
b = points[j+1]
line(a.x, a.y, b.x, b.y)
end
elseif body.shapeType == CIRCLE then
strokeWidth(3.0)
end

popMatrix()
end
end

``````

I think my aabb drawing technique seems to be working—also please check out how it looks on all the default PhysicsLab projects included with IntersectionLab—and that any results that look odd are not the code being wrong, they’re us not understanding the reason for the results.

• Posts: 9,584

@UberGoober That looks nice, but I haven’t looked at why the collision isn’t happening all the time. Maybe while I’m watch football this afternoon, I’ll look thru your code.

• edited October 3 Posts: 9,584

I think the problem with the collisions is because you’re overriding the physics engine by moving the square with the touch function. Need to move it using applyForce so the physics code is doing everything.

• Posts: 1,379
@dave1707 can you provide an example? When I try to make precise movements with linear velocity I always mess it up.
• edited October 3 Posts: 9,584

Here’s your code modified a little to use appleForce instead of linearVelocity. I changed the gravity so the square falls. I also made the lower square static so it doesn’t fall. To move the upper square, with your finger below mid screen, slide your finger near the left side to move it left and right side to move it right. To move it up, slide your finger anywhere above mid screen.

It looks like all that’s happening is the black background is just the max size of the square as it rotates.

``````viewer.mode=FULLSCREEN

function boundsOf(body)
local ll, ur = body.position, body.position
if body.shapeType == CIRCLE then
else
for _, thisPoint in ipairs(body.points) do
local worldPoint = body:getWorldPoint(thisPoint)
if worldPoint.x <= ll.x then ll.x = worldPoint.x end
if worldPoint.y <= ll.y then ll.y = worldPoint.y end
if worldPoint.x >= ur.x then ur.x = worldPoint.x end
if worldPoint.y >= ur.y then ur.y = worldPoint.y end
end
end
return ll, ur
end

function tableHas(targetTable, candidate)
if not targetTable or not candidate then return end
for key, element in pairs(targetTable) do
if element == candidate then return key end
end
end

function setup()

rectMode(CENTER)
stroke(74)
strokeWidth(2)
physics.gravity(vec2(0,-5))

s1=physics.body(CIRCLE,60)
s1.x=WIDTH/2
s1.y=HEIGHT/2+200
s1.type=STATIC

r1=physics.body(POLYGON,vec2(-40,40),vec2(-40,-40),vec2(40,-40),vec2(40,40))
r1.x=WIDTH/2
r1.y=300
r1.type=STATIC

tx,ty=WIDTH/2-300,HEIGHT-300

r2=physics.body(POLYGON,vec2(-40,40),vec2(-40,-40),vec2(40,-40),vec2(40,40))
r2.x=tx
r2.y=ty

end

function drawAABB()
local all = physics.queryAABB(vec2(0,0),vec2(WIDTH, HEIGHT))
for _, body in ipairs(all) do
local ll, ur = boundsOf(body)
if ll and ur then
local foundUpper, foundLower, foundRight, foundLeft, foundBounds
local yUp, yDown, xLeft, xRight = 0, 0, 0, 0
--find left edge
local bodiesToLeft = physics.queryAABB(vec2(0,0), vec2(ll.x - xLeft, HEIGHT))
if tableHas(bodiesToLeft, body) then
xLeft = xLeft + 1
else
xLeft = xLeft - 1
foundLeft = true
end
end
--find right edge
local bodiesToRight = physics.queryAABB(vec2(ur.x + xRight, 0), vec2(WIDTH, HEIGHT))
if tableHas(bodiesToRight, body) then
xRight = xRight + 1
else
xRight = xRight - 1
foundRight = true
end
end
--find top
local bodiesAbove = physics.queryAABB(vec2(0, ur.y + yUp), vec2(WIDTH, HEIGHT))
if tableHas(bodiesAbove, body) then
yUp = yUp + 1
else
yUp = yUp - 1
foundUpper = true
end
end
--find bottom
local bodiesBelow = physics.queryAABB(vec2(0, 0), vec2(WIDTH, ll.y - yDown))
if tableHas(bodiesBelow, body) then
yDown = yDown + 1
else
yDown = yDown - 1
foundLower = true
end
end

ur.x = ur.x + xRight
ur.y = ur.y + yUp

ll.x = ll.x - xLeft
ll.y = ll.y - yDown

foundBounds = true
end
pushStyle()
rectMode(CORNER)
fill(0)
rect(ll.x, ll.y, ur.x - ll.x, ur.y - ll.y)
popStyle()
end
end
end

function draw()
background(233, 218, 80)

drawAABB()

q=physics.queryAABB(vec2(tx-40,ty-40),vec2(tx+40,ty+40))
if #q > 1 then
fill(0,255,0)
end

bodiesDraw({r1, r2, s1})
end

function touched(t)
if t.state==BEGAN or t.state==CHANGED then
if t.y<HEIGHT/2 then
if t.x>r2.position.x then
r2:applyForce(vec2(10,0))
elseif t.x<r2.position.x then
r2:applyForce(vec2(-10,0))
end
else
if t.y>r2.position.y then
r2:applyForce(vec2(0,10))
end
end
end
end

function bodiesDraw(bodies)
for i,body in ipairs(bodies) do
pushMatrix()
translate(body.x, body.y)
rotate(body.angle)

if body.type == STATIC then
stroke(255,255,255,255)
elseif body.type == DYNAMIC then
stroke(150,255,150,255)
elseif body.type == KINEMATIC then
stroke(150,150,255,255)
end

if body.shapeType == POLYGON then
strokeWidth(3.0)
local points = body.points
for j = 1,#points do
a = points[j]
b = points[(j % #points)+1]
line(a.x, a.y, b.x, b.y)
end
elseif body.shapeType == CHAIN or body.shapeType == EDGE then
strokeWidth(3.0)
local points = body.points
for j = 1,#points-1 do
a = points[j]
b = points[j+1]
line(a.x, a.y, b.x, b.y)
end
elseif body.shapeType == CIRCLE then
strokeWidth(3.0)
end

popMatrix()
end
end
``````
• Posts: 1,379
This version has the AABB drawing routine applied to all the physics lab tests.

Usually if you run the “sensors” test, and sometimes when you run the “filtering” test, once everything is still you can see an aabb region that isn’t a product of rotation and that exceeds the regular rectangular boundary of the shape (screenshot included).

I’m still not clear if you’re doubting that aabb sometimes incorporates momentum.
• Posts: 9,584

@UberGoober When an object is falling, I can see the bounding area increase in size above and below the object. I also see as the object rotates that the bounding area increases or decreases to keep a rotating object enclosed in it. I agree with you that it increases depending on its speed and direction. It’s just that in your one example it was increasing in size by a lot on all 4 sides even though it was barely moving. So I don’t have a problem with it.

If the aabb function is used just to determine collisions, I’ll just let the collide function determine the collision. It takes care of the collisions with any shaped object.

• Posts: 1,379
In the sensor example you can see the aabb area stretch out behind the box as it falls, and then once it hits the ground the aabb box (usually) stays extended beyond the boundaries of the physics body even though the physics body has stopped moving.

Honestly I don’t know what aabb boundaries are for, but they do seem to be working the way they’re supposed to, and most importantly the way they work is a lot different from the way the documentation says they work.
• Posts: 9,584

@UberGoober They had me confused too. I didn’t know that the bounding area stretched in front and behind a moving object. I guess that’s the fun part of Codea, trying to figure out what’s really happening and creating examples to show it.

• Posts: 1,379

@dave1707 clearly we have vastly different ideas of fun Kudos to Codea for being a good tool for both of us.

• Posts: 1,379

@dave1707 I want to see what happens to aabb boundaries around a circle that’s rapidly moving in an elliptical orbit.

I am no good at all the sine and cosine stuff to make that kind of motion happen—but you’re a pro at that right? Would you be willing to share some basic code for describing a circular orbit?

• edited October 3 Posts: 9,584
``````viewer.mode=FULLSCREEN

function setup()
fill(255)
physics.gravity(vec2(0,0))

s1=physics.body(CIRCLE,50)
s1.x=0
s1.y=0

ang=0
speed=1
end

function draw()
background(0)
ang=ang+1
ellipse(s1.x,s1.y,100)
ang=ang+speed
end
``````
• Posts: 1,379

@dave1707 further somewhat-interesting results.

I applied your code to a physics body, and at the same time I made a circle that uses a `REVOLUTE` joint and angular velocity to achieve elliptical motion—in other words, a body that achieves circular motion just using the physics engine.

Of note:

• the aabb rect of the manually-positioned circle actually lags behind the circle as it travels, meaning the circle is often outside its own aabb rect… which is odd…
• the aabb rect of the manually-positioned circle never changes size—it’s always the size of the minimum rect needed to enclose the circle, no matter how fast it goes
• the aabb rect of the circle moved by the physics engine never lags behind—even at the same or greater speeds than the manually-positioned one, it always fully encloses the circle
• the aabb rect of the circle moved by the physics engine does change size as the circle moves, and the faster it moves the larger it gets.