RigsOfRods / rigs-of-rods

Main development repository for Rigs of Rods soft-body physics simulator
https://www.rigsofrods.org
GNU General Public License v3.0
1.01k stars 178 forks source link

Interconnecting actor woes #2974

Open ohlidalp opened 1 year ago

ohlidalp commented 1 year ago

2973 opens up the nasty topic of connecting actors together at all.

Interconnecting beams

Under the hood, every actor has it's own pool of nodes and beams, and the beam which interconnects actors always belongs to one of them. Until 2014-2015 this was handled by a lot of if()-s in calcBeams() which somehow worked but broke with multithreading. Ulteq invested a lot of energy to find a solution and finally added calcBeamsInterActor() (modified copypaste of calcBeams()) which processes just the interconnecting beams, and a good deal of code to determine and track which beams are interconnecting. But there are still edge cases IIRC.

Transferring forces

In a physics simulation, position of nodes is calculated (integrated) based on forces and time. Setting the forces directly is prone to break numeric stability. We have multiple means of interconnecting actors (ropes, ties, locks...) and IIRC each works slightly differently and I've definitely seen position being copied from one node to another. This is a hazzard which we must eliminate. The only acceptable way of applying any external force to a node (be it from other actor, or user interface, or script, or anything else) is... well, to apply force.

Multithreading

Presently we do simulation in 2 phases: 1. each actor n/b and intra-collisions are simulated on it's own thread (using thread pool) 2. interconnecting beams and inter-actor collisions are simulated on shared physics thread. This means that if you have just 1 local actor (the common case!), you're using just single CPU core.

I have a solution in mind

Under the hood, merge all actors into one huge, permanently active n/b pool, and keep one extra dummy pool permanently sleeping. Keep the existing N/B logic around for spawning and repair/reset, just do simulation on this common pool. To sleep or wake up, swap the N/B between those. This would ellegantly solve the interconnecting problem as any beam would be technically on the same actor. This would also allow us to replace the threadpool by "symmetric multiprocessing" where the workload is equally split in all available CPU cores.

ohlidalp commented 1 year ago

Related: https://github.com/RigsOfRods/rigs-of-rods/pull/3057 - adding MSG_SIM_ACTOR_LINKING_REQUESTED fixes a threading hazard, but the performance concerns still apply