Try OnePhysics’s 3D engine: a sphere dropped on a box, and a cloth draped over a block, with a snapshot and a world hash like the 2D engine’s.
The 3D engine is a preview inside the preview, marked [Experimental("OPHYS0002")]: it works and is deterministic, but its API and results may change between previews. Using it is a compiler error until you acknowledge that, here with #pragma warning disable OPHYS0002.
#pragma warning disable OPHYS0002 // the 3D engine is a preview using RecursiveAI.OneMath; using RecursiveAI.OnePhysics; using RecursiveAI.OnePhysics.Physics3D; var world = new PhysicsWorld3D(); world.AddBox(new Vector3F(20, 1, 20), at: new Vector3D(0, -0.5, 0), type: BodyType.Static); var ball = world.AddSphere(0.5f, at: new Vector3D(0, 5, 0)); ball.OnCollisionEnter += c => Console.WriteLine($"ball hit the ground along {c.Normal}"); // A cloth dropped over a box (soft bodies are new in 0.4.0-preview.1). world.AddBox(new Vector3F(1, 1, 1), at: new Vector3D(3, 0.5, 0), type: BodyType.Static); SoftBody cloth = world.AddCloth(width: 2f, depth: 2f, segments: 16, at: new Vector3D(3, 2, 0)); for (int i = 0; i < 180; i++) world.Step(1f / 60); Console.WriteLine($"ball at {ball.Position}"); Console.WriteLine($"cloth middle at {cloth.GetPosition(8 * 17 + 8)}, corner at {cloth.GetPosition(0)}"); if (world.Raycast(new Vector3D(0, 10, 0), new Vector3F(0, -1, 0), out var hit)) Console.WriteLine($"ray hit at {hit.Point}"); Console.WriteLine($"snapshot {world.Snapshot().Length} bytes, hash {world.ComputeHash():X16}");
ball hit the ground along (-0, -1, -0) ball at (0, 0.49990872712805867, 0) cloth middle at (2.996202104142867, 1.0705060136970133, -0.0004592029581544921), corner at (2.1870665550231934, 0.42688015825115144, -0.7950175404548645) ray hit at (0, 0.9999087271280587, 0) snapshot 29448 bytes, hash 14867385E479387F
Good to know
- The 3D world has the same members as the 2D one, with 3D math types:
PhysicsWorld3D,AddBox,AddSphere,Raycast,Snapshot,ComputeHash. - Soft bodies are new in 0.4.0-preview.1:
AddCloth,AddSoftBoxandAddSoftBallwith theCloth,RubberandJellymaterials, orAddSoftBodyfrom your own triangle or tetrahedral mesh. Particles collide with every shape and with each other and push dynamic bodies.GetPosition(i)reads one particle without allocating; particle8 * 17 + 8is the middle of a 16-segment cloth. - 3D also has characters, vehicles, ragdolls and buoyancy. Results are bit-identical across x64, arm64, WebAssembly, vector widths and thread counts.
See soft bodies and the changelog.