Simple-Station / Einstein-Engines

A Space Station 14 upstream repository, inspired by Baystation12.
GNU Affero General Public License v3.0
46 stars 123 forks source link

Physics Based Air Throws #342

Closed VMSolidus closed 2 months ago

VMSolidus commented 5 months ago

Description

I've made it so that when a room is explosively depressurized(or when a body of high pressure air flows into one of lower pressure air), that entities inside are launched by the air pressure with effects according to their mass. An entity's mass is now used as an innate resistance to forced movement by airflow, and more massive entities are both less likely to be launched, and will launch less far than others. While lighter entities are launched far more easily, and will shoot off into space quite quickly! Spacing departments has never been so exciting! This can be made extraordinarily fun if more objects are given the ability to injure people when colliding with them at high speeds.

As a note, Humans are very unlikely to be sucked into space at a typical force generated from a 101kpa room venting into 0kpa, unless they happened to be standing right next to the opening to space when it was created. The same cannot be said for "Lighter-Than-Human" species such as Felinids and Harpies. I guess that's just the price to pay for being cute. :)

On a plus side, because the math behind this is simplified even further than it was before, this actually runs more efficiently than the previous system.

TODO

Nothing, this is basically done. I've spent a good 6 hours straight finely tuning the system until I was satisfied that it reflects something close to reality.

MEDIA

Before the Space Wind Rework:

https://github.com/Simple-Station/Einstein-Engines/assets/16548818/0bf56c50-58e6-4aef-97f8-027fbe62331e

With this Rework:

https://github.com/Simple-Station/Einstein-Engines/assets/16548818/6be507a9-e9de-4bb8-9d46-8b7c83ed5f1d

Changelog

:cl: VMSolidus

VMSolidus commented 5 months ago

Certainly very impressive, and I like the effect a lot. I am concerned by the sheer number of variables being discarded (I didn't even note them all!). Even if we feel they aren't required here, they also may just be unused now, and modifying them may not have the implied effect.

Any idea why the items on the table to the left of the breach in the video seem to be unaffected, while things much further away in the room are blasted?

That one's an interesting thing to look at. Since objects can only be moved if the force of the air flow is greater than the square of their mass, objects that are lightweight are pulled from farther away(If you look at the top right, you can see that the pens from the Dev medbay were transported all the way from medical to the hole), while objects that are heavier need to be relatively close. The force being applied scales inversely with distance, and the size of the hole in question has an effect on how much force can be applied. The C4 made a very large hole, which in turn spread the force out over a much wider area. The heavier steel on the left wasn't affected because the force wasn't great enough.

I've also noticed that the relative geometry of the hallways leading up to the hole have their own effects on the airflow.

VMSolidus commented 5 months ago

image

I haven't actually removed the variables from the system, reasoning that someone may inevitably try to use them. But they were all either Constants or CVars, not really true math variables. I'm actually not modifying any variables that get passed back, just usingh what information was already available to the function via its access to PhysicsComponent. Another function elsewhere already derives the force of a pressure differential. I did however need to keep some of the exit conditions, because technically the equation I have replaced this with is a parametric equation, it must have some form of limit.

image

Actually, now that you mention it, because I am dividing by true variables and not constants, I now need to go back and address potential divide by zero exits.

VMSolidus commented 5 months ago

https://github.com/Simple-Station/Einstein-Engines/assets/16548818/75f74969-5da0-4bf9-8bdf-70ce158b8b9e

https://github.com/Simple-Station/Einstein-Engines/assets/16548818/23de7a87-dcd7-48b8-9768-b7c20f9666d5

VMSolidus commented 5 months ago

Psprite don't merge this yet, I have a pretty good idea how I'm going to reimplement the speed clamp. It basically just means I need to test constants. In ApplyLinearImpulse(uid, vector, physicscomponent), vector is given in the form r(costhetai + sinthetaj), and in this case dirVec is a vector based on an r=1 circle, and moveForce is my value for r. I simply need to replace these two uses of moveForce with Math.Clamp(moveForce, 0, constant)

And then brute force test constants in a dev environment until I find one where it's impossible to fling a sheet of paper through a steel wall.

rosieposieeee commented 5 months ago

hahahahahaha this fucking rules, oh my god

bit odd that the mouse and the urist arent affected, though

VMSolidus commented 5 months ago

Okay! I've added the clamp back in, and did some rather extreme limit testing to determine that this actually is a good number to set the velocity limit to, which is to say it cannot exceed 30 meters per second of acceleration.

VMSolidus commented 5 months ago

This is now ready for some excellent reviews.

VMSolidus commented 5 months ago

While examining the equations, I figured out another small optimization. Physics components contain an Inverse Mass, equal to 1/Mass. Since multiplication runs faster than division, I can make a small optimization to the equation by multiplying by InvMass instead of dividing by Mass, achieving the same result faster. Since this is a physics system that runs hundreds of times per tick, every small improvement matters a lot.

Getting rid of the division sign means its also no longer possible to divide by zero, so we no longer need to check if mass is 0 to prevent division by zero errors.

VMSolidus commented 4 months ago

I've added a Before and After video demonstration to this PR, showing what exactly has been changed.

VMSolidus commented 4 months ago

A solution needs to be thought of to prevent human-mobs from being untouched. The realism of it is quite unimportant- people need to be able to get flung into space.

This could be making the amount that mass impacts diminishing so that very heavy things can still be flung, or it could be giving mobs Components to change how they're impacted by depressurization.

I will outright refuse this Psprite because that is extremely, ridiculously out of scope for this PR, because it would necessitate completely rewriting how air flow is calculated in the first place. The original system literally just generated a random number and then used that random number to decide if a human was to be thrown. As a stopgap for the equations for air flow simply being not up to par.

VMSolidus commented 4 months ago

A solution needs to be thought of to prevent human-mobs from being untouched. The realism of it is quite unimportant- people need to be able to get flung into space.

This could be making the amount that mass impacts diminishing so that very heavy things can still be flung, or it could be giving mobs Components to change how they're impacted by depressurization.

Additionally, I attempted solutions in testing for creating a stopgap to throw humans more consistently, and it had run into many of the same problems the original creator did, where if even the tiniest of player character throws happened, it made the game feel extremely awful to play due to the system constantly wresting control from the player. Fixing that is also out of scope for this PR.

VMSolidus commented 4 months ago

A solution needs to be thought of to prevent human-mobs from being untouched. The realism of it is quite unimportant- people need to be able to get flung into space.

This could be making the amount that mass impacts diminishing so that very heavy things can still be flung, or it could be giving mobs Components to change how they're impacted by depressurization.

So I'll, give it an attempt to find a solution to this, but I'll preface it with this. This is an extremely tick intense physics system. This function I optimized runs thousands of times per tick, and every individual line added to it runs up the frametime on an already incredibly frametime hungry system. Adding unnecessary component checks won't do, adding even more math checks here won't do. That improvement you're asking for is going to take making a significant improvement elsewhere, namely in airflow. Airflow pathfinding is extremely bad, creating unusually deep pockets of ultra-fast moving air, while vast portions of the station don't receive anywhere close to the pressure differential that physics dictates they should. For one airflow is only orthogonal adjacent. If I can free it up to perform diagonal movement too, that should in turn dramatically improve the ability of it to throw objects in unusual places, or for heavier objects. That would also allow air to throw objects diagonally, instead of just orthogonal.

For me to accommodate this specific request, I am not going to find a satisfactory solution for it in the function this PR touches.

DEATHB4DEFEAT commented 4 months ago

This function I optimized runs thousands of times per tick

That should not happen for anything, no wonder it sucks for performance

VMSolidus commented 4 months ago

This function I optimized runs thousands of times per tick

That should not happen for anything, no wonder it sucks for performance

I managed to find a extremely common exit condition that bypasses almost 200 lines of script. It should run about 1/100th as often now.

VMSolidus commented 4 months ago

@Pspritechologist I have implemented most of your requested changes, but one in particular is essentially impossible to do within the scope of this PR.

VMSolidus commented 4 months ago
github-actions[bot] commented 4 months ago

This pull request has conflicts, please resolve those before we can evaluate the pull request.

github-actions[bot] commented 4 months ago

This pull request has conflicts, please resolve those before we can evaluate the pull request.

VMSolidus commented 3 months ago

This is ready for review. @DEATHB4DEFEAT @Pspritechologist @DangerRevolution @Peptide90 @OldDanceJacket

Aidenkrz commented 3 months ago

I believe when we last talked about this, the maxvelocity cvar wasn't working correctly, and you were going to reimplement it after changing up some of the math as it currently does nothing.

VMSolidus commented 3 months ago

I believe when we last talked about this, the maxvelocity cvar wasn't working correctly, and you were going to reimplement it after changing up some of the math as it currently does nothing.

Thanks for the reminder, re implementing the max velocity was actually pretty easy. image

VMSolidus commented 3 months ago

I believe when we last talked about this, the maxvelocity cvar wasn't working correctly, and you were going to reimplement it after changing up some of the math as it currently does nothing.

Actually, do you mind passing me your improvements to TileRipping? I'd like to bring them here if they work well enough there.

Aidenkrz commented 3 months ago

Actually, do you mind passing me your improvements to TileRipping? I'd like to bring them here if they work well enough there.

Already deleted the branch, it was pretty terrible code that I just threw together in five minutes for a proof of concept. IIRC essentially all i did was add a counter that ticked up from the start of it being called, multiply it by a random float, and then multiply the delta by that.

DangerRevolution commented 3 months ago

Going to play around with this pre-review; while I do like the DS14 version, still worth testing. This should be held off from merging until @DEATHB4DEFEAT and/or @Pspritechologist review it too due to the importance/scale :)