Nimbin[12]?SDL & Graphics / sdl_runtime_compiler / benchmark/bench_collision.cpp

sdl_runtime_compiler git · main

SDL3 game for running and compiling code at runtime

sdl3 c++ compiler dlopen cmake · first commit 2026-04-19 · last commit 2026-07-03 (3 months ago) · synced 3 days ago · upstream: git.ide3.de/hsnr/sdl-runtime-compiler

C++ 72.3% C 26.2%
git clone https://git.christianimmanuel.de/sdl-graphics/sdl_runtime_compiler.gitwget https://git.christianimmanuel.de/sdl-graphics/sdl_runtime_compiler/archive/sdl_runtime_compiler.tar.gz
benchmark/bench_collision.cpp 4.3 KB · 113 lines raw
#include <benchmark/benchmark.h>
#include <vector>

#include "systems/collision.hpp"
#include "entities/solid_box.hpp"
#include "utils/globals.hpp"
#include "utils/math.hpp"

namespace
Nimbin
{

// How does collision cost scale with the number of objects?

// ──────────────────────────────────────────────────────────────────────────
// Pure math benchmarks — no GameObject, just the algorithm
// ──────────────────────────────────────────────────────────────────────────

static void BM_SweptRayAabb_Hit(benchmark::State& state)
{
    Vec3 origin { 0.0, 0.0, 0.0 };
    Vec3 dir    { 1.0, 0.0, 0.0 };
    Vec3 bmin   { 0.5, -0.5, -0.5 };
    Vec3 bmax   { 1.5,  0.5,  0.5 };

    for (auto _ : state) {
        Collision::SweptResult sw = Collision::swept_RayAabb(origin, dir, bmin, bmax);
        benchmark::DoNotOptimize(sw);
    }
}
BENCHMARK(BM_SweptRayAabb_Hit);


static void BM_SweptRayAabb_Miss(benchmark::State& state)
{
    Vec3 origin { 0.0, 0.0, 0.0 };
    Vec3 dir    { 1.0, 0.0, 0.0 };
    Vec3 bmin   { 0.5,  5.0, -0.5 };   // above the ray
    Vec3 bmax   { 1.5,  6.0,  0.5 };

    for (auto _ : state) {
        Collision::SweptResult sw = Collision::swept_RayAabb(origin, dir, bmin, bmax);
        benchmark::DoNotOptimize(sw);
    }
}
BENCHMARK(BM_SweptRayAabb_Miss);


// ──────────────────────────────────────────────────────────────────────────
// GameObject-based — includes the yaw-aware aabb_min/max cost
// ──────────────────────────────────────────────────────────────────────────

static void BM_AabbOverlap_Yawed(benchmark::State& state)
{
    // SolidBox is the simplest concrete GameObject.
    SolidBox a({0,0,0}, {0.5, 0.5, 0.5});
    SolidBox b({0.4, 0.0, 0.0}, {0.5, 0.5, 0.5});
    a.yaw = 0.7f;   // exercise the yaw-aware AABB path
    b.yaw = 1.2f;

    for (auto _ : state) {
        bool hit = Collision::aabb_Overlap(a, b);
        benchmark::DoNotOptimize(hit);
    }
}
BENCHMARK(BM_AabbOverlap_Yawed);


static void BM_AabbOverlap_AxisAligned(benchmark::State& state)
{
    SolidBox a({0,0,0}, {0.5, 0.5, 0.5});
    SolidBox b({0.4, 0.0, 0.0}, {0.5, 0.5, 0.5});
    // yaw = 0 by default

    for (auto _ : state) {
        bool hit = Collision::aabb_Overlap(a, b);
        benchmark::DoNotOptimize(hit);
    }
}
BENCHMARK(BM_AabbOverlap_AxisAligned);


// ──────────────────────────────────────────────────────────────────────────
// Scaling: how does pair-collision cost grow with N?
// This is the O(N²) loop in PhysicsSystem::update_Objects.
// ──────────────────────────────────────────────────────────────────────────

static void BM_PairwiseOverlap_Scaling(benchmark::State& state)
{
    const size_t N = static_cast<size_t>(state.range(0));

    // Build N boxes in a grid so most pairs don't overlap.
    std::vector<SolidBox> boxes;
    boxes.reserve(N);
    for (size_t i = 0; i < N; ++i) {
        double x = static_cast<double>(i % 10) * 2.0;
        double z = static_cast<double>(i / 10) * 2.0;
        boxes.emplace_back(Vec3{x, 0.0, z}, Vec3{0.5, 0.5, 0.5});
    }

    for (auto _ : state) {
        int hits = 0;
        for (size_t i = 0; i < N; ++i)
            for (size_t j = i + 1; j < N; ++j)
                if (Collision::aabb_Overlap(boxes[i], boxes[j])) ++hits;
        benchmark::DoNotOptimize(hits);
    }

    state.SetLabel("N=" + std::to_string(N) + " pairs=" + std::to_string(N*(N-1)/2));
}
BENCHMARK(BM_PairwiseOverlap_Scaling)->Arg(10)->Arg(25)->Arg(50)->Arg(100)->Arg(200);

} // namespace Nimbin