module Main (main) where import Control.Monad (forM_) import Test.Tasty.Bench import Box3D.Body qualified as Body import Box3D.Id (WorldId) import Box3D.MathTypes import Box3D.Shape qualified as Shape import Box3D.Types import Box3D.World qualified as World {- | Build a world holding @n@ dynamic spheres dropped onto a static ground sphere, so that a step exercises broad phase, narrow phase and the solver. -} setupWorld :: Int -> IO WorldId setupWorld n = do wd <- defaultWorldDef -- keep the pile awake: a settled world would otherwise fall asleep and -- the stepping benchmarks would measure an idle no-op step w <- World.create wd{worldDefGravity = Vec3 0 (-10) 0, worldDefEnableSleep = 0} gd <- defaultBodyDef ground <- Body.create w gd gsd <- defaultShapeDef _ <- Shape.createSphere ground gsd (Sphere vec3Zero 10) bd <- defaultBodyDef sd <- defaultShapeDef forM_ [0 .. n - 1] $ \i -> do let col = fromIntegral (i `mod` 8) row = fromIntegral (i `div` 8) position = Vec3 (col - 4) (12 + row) 0 b <- Body.create w bd{bodyDefType = DynamicBody, bodyDefPosition = position} _ <- Shape.createSphere b sd (Sphere vec3Zero 0.5) pure () -- let the pile settle so steps hit a steady contact load forM_ [1 .. 120 :: Int] $ \_ -> World.step w (1 / 60) 4 pure w main :: IO () main = do emptyDef <- defaultWorldDef world64 <- setupWorld 64 world256 <- setupWorld 256 defaultMain [ bench "World.create + World.destroy" $ whnfIO (World.create emptyDef >>= World.destroy) , bench "step 64 spheres" $ whnfIO (World.step world64 (1 / 60) 4) , bench "step 256 spheres" $ whnfIO (World.step world256 (1 / 60) 4) ]