It's debateable whether this is a Godot question or just me making an embarrassing hash of high school physics...
I've got a basic Newtonian solar system sim with n-body gravity:
func _physics_process(delta):
apply_gravity(delta)
func apply_gravity(delta):
for p1 in planets:
for p2 in planets:
if p1 == p2:
continue
p1.velocity += newtonian_force(p1, p2) * delta
func newtonian_force(p1, p2):
var r = p1.global_transform.origin.distance_to(p2.global_transform.origin)
var dir = (p2.global_transform.origin - p1.global_transform.origin).normalized()
if r < 1:
return Vector3.ZERO
return dir * G * p2.mass / (r*r)
The above works fine, I can spawn countless planets orbiting merrily around a sun. It's chaotic though.
So I want to make moons upon moons upon moons in circular orbits. So all I need to do is set the tangential velocity vector to make a stable orbit:
func set_orbital_velocity(parent_body):
var dir = (parent_body.global_transform.origin - global_transform.origin).normalized().cross(Vector3.UP)
var r = global_transform.origin.distance_to(parent_body.global_transform.origin)
velocity += dir * sqrt(get_parent().G * parent_body.mass/r)
The parent_body
is the object it's orbiting. So for a moon, I'll run this first sending the sun as an argument, then for the planet it's orbiting, etc, down the tree.
Except I don't get perfect orbits and I don't get why. Even with a simple 3-body problem.
Surely mass* v*v = (G * mass * parent_body.mass) / (r*r)
mass cancels so v*v = (G * parent_body.mass) / r
so to get v
for a circular orbit surely it's just: v = sqrt(G*parent_body.mass / r)
How does that not give me circular orbits?? I've tried staring indignantly at my screen but even that didn't fix it. ;)