PhysX/Havok are out, PRF Physics are in (for Vigilante)

 For Vigilante Racer, I designed a physics system to replace PhysX/Havok, which is proving far more performant. I used to think this would be insanely tough, but not so much. The video below shows the original PhysX based antigravity system, which worked, but had a lot of blind spots. 


The lines from the corner of the car were its physics checks with the world around it, to try to detect how close things were, and how much they affected the car. For instance, if something moved right up to the side of the car, the car would naturally push away. 

Now it can only check where the lines where checking, and each corner of the car was checking 7 directions. (X, Y, Z, XY, XZ, YZ, XYZ axis combinations) But if something was directly above, it wouldn't feel it, because there were no checks. So for a single car, every physics frame required 29 physics checks. (4x7+1, the +1 was used from the center of the car to re-align gravity)

Before coming to the solution I have now, I had looked at baking physics probes into the world, which would query the world around more expensively at build, but then have a good memory structure to pull up this information, and then each engine would just look up the memory fragment closest to itself to retrieve the forces to apply. so each baked point would replace 7 physics look ups, but since they could bake with more details, that could easily mean 1000 physics ray cast look ups. 

However, around the time I started designing memory structure for this, I also learned about SDF physics. Which is basically a function that you pass in a point to, and it tells you if you are inside the object by returning which direction and magnitude distance to move. SDF of complex objects can be done like a pixel map, where you determine the resolution, and the color, would show how far from an edge you are. The image below (from Signed distance function - Wikipedia) shows a rubber ducky shape generated from this. 


However, rather than needing a grid of memory to store these distances, and still not be completely accurate (some details are important), SDF can also be a simple function that mathematically understands the physical shape it takes on. A perfect example is a sphere. 1 point in the middle and a radius is all it takes. Then no matter how high of a resolution you check, you will always get 100% perfect physics shape.

Now SDF doesn't quite solve my physics problem, but it was quite close. Rather than understand the physical boundaries, I needed a normal that was pushing away from the object and a power level to apply. So now it becomes, "Can I generate a function that will mathematically understand a fragment of the world. The more complicated the world, the harder it is to define. 

The floor is easy. If all the world has a ground at 0, and a gravity pushing down towards it, then I can have a floor function that simply looks at the Y value (Unity up axis) and returns Vector3.up and a power related to how much force in that direction the car engine needs to apply. When I want an angled surface, I can rotate the object and to a transform check. I can also lock it to a region related to the transform scale, using the Y axis as a proximity range. 

I call this system PRF (Proximity Repulsion Field), as it is used to repulse the hover car engines. 

Here is 50,653 physics points being checked in real (under 30ms) time on 1 CPU. I later plan to move this to GPU. 


50,000 physics points is how much would be needed to process 10,000 cars in physics in real time. Each car uses 5 points, though could get by with 4, though I haven't like the 4 check feel as much as 5 checks.  Which is a goal I'm aiming for with this engine. I don't know if I'll be able to reach it once I have added a few more systems. This design was built around LOD physics, so I should be able to keep things moving properly. 10k anti-gravity cars won't all be in close rendering, so many can be pushed to LOD rendering, LOD physics. Improving as you get closer to them. 

I will be creating a system that bakes probes for which physics function to use at various points, with comprehension of how those points link, so we can easily move through memory via a 3D point to memory index, so looking up physics for where something is should be light weight as well. 

Here is the basic layout now. I'm sure I'll have many improvements, but for now here it is. 


For any given point, we provide a world position, and then build up a total force applied by all the forces affecting that point. Typically this will be under 4. It relates to design practices, so the more complex an environment, the more force queries there are, however, entire winding tunnels and skyways can be done with a single force query. An offramp would be one function. A building might be one function, or an entire city could be a function, if I have an equation that relates to the design layout of the city. Part of it will be based on generating tools that a designer can then apply in various flexibilities. Splines are solved. (I don't have split splines solved though, only in theory so far)

Here is a query for a simple infinite floor force. 


And here is the query for an angled surface fragment (a square).


50% of the processing time when to looking up transforms. This is needed to allow for movement and testing. But once baked, this information would already be available, and I can work on having the transform matrix already locked/stored and ignore Unity's transform look ups. I'll be in ECS or GPU anyway, so I don't need these. And rendering will be fully separated from the physics structures.  


Comments

  1. A few points I know I can improve:
    1, getting rid of transform lookups. Literally obtaining the transform ate 50% of the CPU time. Holding a local Matrix4x4 for inverse and world transform should solve that.

    2, not normalizing the force/power in the PRF function, but doing that in the combining function. There is an issue where if 2 forces combine at a right angle, and both are powered at 1, then the result is 45 degrees. However I max the power at one, so if one side represents a stronger force it should over power the other. I'll need this for things like Ramps to work, where the spot boosts you, or any competition with surrounding forces will cut if off significantly.

    These are leading concepts on what I'll do next, but maybe not. I think I might focus on dropping a car in there now. And then process a spline and a modified Matrix4x4 (scale/position/rotation are all used)

    ReplyDelete
  2. I'm also using scale to determine width in the existing force functions. That requires matrix math to obtain, and so I could reduce this. I'll possiblty just stay with quaternion for rot, vec3 for position and a width float. I haven't done enough research into matrix math problems, or how its used here, but I want to avoid any unneeded equations.

    Another concern I'll be heading into next is how to manage car to car memory. potentially a double buffer that writes objects in one frame into the memory structure of the next frame. and then back, so that we end up with a better sequence for systems/cachehits. I'll also need to start putting more time into ECS now.

    ReplyDelete

Post a Comment