"Gravity well" in Box2D

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
emanevitaerc
Prole
Posts: 17
Joined: Sun Mar 13, 2016 7:21 am

"Gravity well" in Box2D

Post by emanevitaerc »

In a very crude space simulation using Love's physics, is there a way to roughly implement the attraction of bodies to each other based on their mass and density? I know using the world's gravity wouldn't make any sense since it's a single direction imposed on every body within it; all I'm really looking to do is have bodies have an attraction to the center of mass of other nearby bodies. Would it take too much processing power, or are there other problems that just make it impractical?

On a somewhat unrelated note, I think more physics tutorials on the wiki would be nice. The only one up right now is a decent introduction, but doesn't even begin to cover all the functionality.
Skeletonxf
Citizen
Posts: 87
Joined: Tue Dec 30, 2014 6:07 pm

Re: "Gravity well" in Box2D

Post by Skeletonxf »

Not too sure about how you implement it into Love's physics but the equation for gravitational force in real life is fairly simple

F = -(GMm)/(r^2)

where G is a constant and M and m are the two point masses where m orbits M and r is the orbit distance (density doesn't matter). For something like Pluto and its moons this formula doesn't work because the moons and Pluto are similar enough in mass that the moons have a noticeable pull on Pluto, but for bodies where a moving small one orbits a stationary one you should find this works well.
User avatar
s-ol
Party member
Posts: 1077
Joined: Mon Sep 15, 2014 7:41 pm
Location: Cologne, Germany
Contact:

Re: "Gravity well" in Box2D

Post by s-ol »

emanevitaerc wrote:In a very crude space simulation using Love's physics, is there a way to roughly implement the attraction of bodies to each other based on their mass and density? I know using the world's gravity wouldn't make any sense since it's a single direction imposed on every body within it; all I'm really looking to do is have bodies have an attraction to the center of mass of other nearby bodies. Would it take too much processing power, or are there other problems that just make it impractical?

On a somewhat unrelated note, I think more physics tutorials on the wiki would be nice. The only one up right now is a decent introduction, but doesn't even begin to cover all the functionality.
Tutorials are sparse since there are tons of tutorials for "regular" box2d that can be followed exactly in the Lua/LÖVE binding as well.

@Skeletonfx: why would it not work? The Earth's and the moon's mass are also both significant enough for the two to be rotating around a common center thats quite a bit off from the earth's center point. The calcualtion should work regardless.

You just need to calculate the force working between each pair of bodies every frame and apply it to each of them.

s-ol.nu /blog  -  p.s-ol.be /st8.lua  -  g.s-ol.be /gtglg /curcur

Code: Select all

print( type(love) )
if false then
  baby:hurt(me)
end
Skeletonxf
Citizen
Posts: 87
Joined: Tue Dec 30, 2014 6:07 pm

Re: "Gravity well" in Box2D

Post by Skeletonxf »

I should have said it wouldn't work as simply because the bigger object would move non negligibly due to the force on it (which doesn't happen for Earth-moon) and so radius could change
https://en.wikipedia.org/wiki/Newton%27 ... odern_form
If you're willing to loop over every object and apply the force for and to every object then the physics won't be wrong.

Why doesn't it happen for Earth-Moon?
Using data grabbed off wikipedia
Mass of Earth = 5.972 × 10^24 kg
Mass of Moon = 7.348 × 10^22 kg
G: 6.674×10^−11
Avg orbit radius of Moon around Earth (it's an ellipse) 385000 km
Force = - (G * M * m) / r^2
= 1.97*10^20
Acceleration of Earth due to force = F / m = (1.97*10^20) / (5.972 × 10^24) = 0.000033 ms^-2 (2sf)
Negligible
User avatar
airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

Re: "Gravity well" in Box2D

Post by airstruck »

Here's something that looks fairly decent.

Code: Select all

local bodies = world:getBodyList()
local G = 0.0667

for _, b1 in ipairs(bodies) do
    local vx, vy = 0, 0
    for _, b2 in ipairs(bodies) do
        if b2 ~= b1 then
            local x1, y1 = b1:getWorldCenter()
            local x2, y2 = b2:getWorldCenter()
            local m2 = b2:getMass()
            vx = vx + (x2 - x1) * m2
            vy = vy + (y2 - y1) * m2
        end
    end
    b1:applyForce(vx * G, vy * G)
end
I'm not sure how realistic it is (maybe someone more experienced can comment on that), but something along these lines in love.update should be alright for a game where all bodies are attracted to all other bodies.
User avatar
emanevitaerc
Prole
Posts: 17
Joined: Sun Mar 13, 2016 7:21 am

Re: "Gravity well" in Box2D

Post by emanevitaerc »

airstruck wrote:Here's something that looks fairly decent.

Code: Select all

snippy snip
I'm not sure how realistic it is (maybe someone more experienced can comment on that), but something along these lines in love.update should be alright for a game where all bodies are attracted to all other bodies.
This looks to be exactly what I'm looking for, thank you. Maybe it can be optimized by excluding inconsequentially small bodies and just keeping a table for bigger objects.
User avatar
airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

Re: "Gravity well" in Box2D

Post by airstruck »

emanevitaerc wrote:Maybe it can be optimized by excluding inconsequentially small bodies and just keeping a table for bigger objects.
Of course you'll still need to pull small bodies towards big ones, so you might need two tables. Also b1:getWorldCenter() should have been done outside of that inner loop.
User avatar
emanevitaerc
Prole
Posts: 17
Joined: Sun Mar 13, 2016 7:21 am

Re: "Gravity well" in Box2D

Post by emanevitaerc »

airstruck wrote:
emanevitaerc wrote:Maybe it can be optimized by excluding inconsequentially small bodies and just keeping a table for bigger objects.
Of course you'll still need to pull small bodies towards big ones, so you might need two tables. Also b1:getWorldCenter() should have been done outside of that inner loop.
Righty o, thanks for the help.
User avatar
airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

Re: "Gravity well" in Box2D

Post by airstruck »

It just occurred to me that you might be able to do this in O(n) time by calculating the center of mass for all bodies and then adjusting for each body's own position and mass before you apply the force to it. Completely untested, just an idea. Someone with more physics experience might be able to comment.
User avatar
ivan
Party member
Posts: 1911
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: "Gravity well" in Box2D

Post by ivan »

Not a bad example by airstruck, but a more optimal approach might be to handle the gravity between PAIRS of bodies so:

Code: Select all

for i = 1, #bodies do
  local m1 = bodies[i]:getMass()
  local x1, y1 = b1:getWorldCenter()
  for j = i + 1, #bodies do
    -- find the force of gravity between bodies[i] => bodies[j]
    local m2 = bodies[j]:getMass()
    local x2, y2 = b2:getWorldCenter()
    local dx, dy = x1 - x2, y1 - y2 -- distance vector
    local dsq = dx*dx + dy*dy -- distance squared
    assert(dsq > 0, "singularity :)")
    local f = G*m1*m2/dsq -- force
    local idf = 1/math.sqrt(dsq)*f -- inverse distance*force
    local gx, gy = dx*idf, dy*idf -- force vector
    -- apply force to the pair i, j
    bodies[i]:applyForce(gx, gy)
    bodies[j]:applyForce(-gx, -gy)
  end
end
Note that the number of pairs increases rapidly so it would only be practical for up to 200-300 bodies.
G*m1 could be moved outside of the inner loop too.
Also, make sure you set a mass for your static bodies so it's not 0.
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot] and 82 guests