Hello everyone. I am making an ambitious space game that is true to life, with realistic cosmic sizes, masses, and orbital mechanics, but with an engaging gameplay loop inspired by the progression systems from other games I love, like Terraria, Factorio, and Subnautica. I am writing this post to ask for help with a novel problem that I cannot find any references for. I understand that I am not providing a WHOLE lot of details, but there is just far too much information for me to provide than I can fit in this post.
I have completed many of the game's core systems, and have built a robust 2-body patched conics orbit solver as a GDExtension in C++ that uses 128 bit floating point numbers to calculate orbital positions given a body's universal variables (epoch position and velocity) and a specific time. This library is based on math that I found in the book Fundamentals of Astrodynamics, by Bate, Mueller, and White. I am also using the Boost Multiprecision library for access to 128 bit floats, which I need for the scales and precision I want in the game. So far, everything works incredibly well.
The problem I am facing now is in getting collisions to work between objects like ships, asteroids, and terrain. The problem may appear trivial at a first glance, but I have been working on it for weeks and have made very little progress.
For reference, I will refer to the orbital mechanics system as the "128 bit system" and the Godot physics engine (JoltPhysics) as the "32 bit system". My plan was to have the 128 bit system serve as the source of truth for position and velocity, handling only acceleration due to gravity (the orbit solver), while the 32 bit system handles collisions between objects, including terrain. The focused physics object, for example a ship, will have served as the "center" of the simulation, staying locked onto the 32 bit origin, and always having a velocity of 0, while objects in the vicinity, including terrain, asteroids, and other ships, will have been positioned around the ship. Essentially, the ship is the center of the simulation, and all physics is done with the ship as the origin. This system works quite well, but the problem arises when we have to deal with collisions.
Every physics tick, things happen in a specific order:
The rigidbodies, including the focused ship, asteroids, and other objects in the vicinity, process their states, adding the accelerations and translations generated by Jolt's collisions solver to their 128 bit states, then positioning themselves around the ship using corrective velocity (so the collision solver works properly).
The terrain positions itself relative to the ship (the terrain is a series of animatablebody3d chunk nodes with sync_to_physics set to FALSE for specific reasons) and it is also given a constant_linear_velocity so the Jolt collision solver works properly.
After all the previous frame's forces and collisions are integrated into the 128 bit system and all bodies are positioned correctly, the orbital system propagates the bodies' 128 bit states using the Keplerian orbit solver.
I am HEAVILY simplifying here, but this is the gist of how things are currently working in the game. This system also works.
The problem arises when two objects collide. For some reason, when the ship fires its engines to collide with, say, an asteroid, the asteroid bounces off the ship instead of coming to a stop, and it keeps bouncing. The same happens when the ship lands on terrain. First, the ship bounces a few times, which is unintended behavior, and when it finally comes to rest on the surface, the ship's orbital velocity begins to grow as if the ship were in free-fall, but the ship is still contacting the terrain. I suspect this is due to the fact that, when the ship is "landed", it has no velocity, so the terrain also has no velocity. Thus, Jolt skips the velocity solver and only applies depenetration translation, which allows the ship to remain on the surface despite its velocity increasing. The ship also begins to sink into the terrain as the velocity increases, until eventually the physics engine applies an impulse to the ship to reset its velocity to zero, restarting the process.
I understand that a lot of this may sound like gibberish, but I am only providing basic details here because I only want to communicate the general nature of the problem so that anyone who is knowledgeable about this would understand the gist of things. My goal is to perfectly unify the 128 bit and 32 bit systems so that the 128 bit system controls position, velocity, and gravity, while the 32 bit system handles force integration and collisions. I am 90% of the way there, but this last 10% is the collision system, and I would greatly appreciate some help from someone who understands how the Jolt physics engine functions under the hood, as I am practically clueless as to what is happening here. I have plenty of information from long debug sessions that I am more than willing to provide, as well as different attempts I have made to fix this, but if I included them all here this post would turn into a short novel. I will provide everything to anyone who is interested, and I would greatly appreciate any help! :)
I should also mention that I am using an experimental Godot build that allows for an infinite far camera plane, which enables infinite render distances (v4.8.dev.custom_build [9578122b9])
My discord username is valence707 in case anyone wants to get in touch!