LCOV - code coverage report
Current view: top level - src/physics - PhysicsPipelineSystem.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 97.7 % 88 86
Test Date: 2026-04-10 19:03:25 Functions: 100.0 % 5 5

            Line data    Source code
       1              : /*
       2              :  * Copyright (C) 2025 aeml
       3              :  *
       4              :  * This program is free software: you can redistribute it and/or modify
       5              :  * it under the terms of the GNU General Public License as published by
       6              :  * the Free Software Foundation, either version 3 of the License, or
       7              :  * (at your option) any later version.
       8              :  *
       9              :  * This program is distributed in the hope that it will be useful,
      10              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12              :  * GNU General Public License for more details.
      13              :  *
      14              :  * You should have received a copy of the GNU General Public License
      15              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      16              :  */
      17              : 
      18              : #include "physics/Systems.hpp"
      19              : 
      20              : #include <algorithm>
      21              : #include <cmath>
      22              : 
      23              : namespace physics
      24              : {
      25              :     namespace
      26              :     {
      27        28604 :         void SyncDynamicAabbsToTransforms(ecs::World& world)
      28              :         {
      29        28604 :             auto* aabbStorage = world.GetStorage<AABBComponent>();
      30        28604 :             auto* tfStorage = world.GetStorage<TransformComponent>();
      31        28604 :             auto* rbStorage = world.GetStorage<RigidBodyComponent>();
      32        28604 :             if (!aabbStorage || !tfStorage || !rbStorage)
      33              :             {
      34         4497 :                 return;
      35              :             }
      36              : 
      37        24107 :             auto& aabbs = aabbStorage->GetData();
      38        24107 :             const auto& entities = aabbStorage->GetEntities();
      39        24107 :             const size_t count = aabbs.size();
      40       735040 :             for (size_t i = 0; i < count; ++i)
      41              :             {
      42       710933 :                 const ecs::EntityId id = entities[i];
      43       710933 :                 auto* rb = rbStorage->Get(id);
      44       710933 :                 auto* tf = tfStorage->Get(id);
      45       710933 :                 if (!rb || rb->invMass == 0.0f || !tf)
      46              :                 {
      47        70161 :                     continue;
      48              :                 }
      49              : 
      50       640772 :                 auto& aabb = aabbs[i];
      51       640772 :                 const float halfW = std::max(0.0f, (aabb.maxX - aabb.minX) * 0.5f);
      52       640772 :                 const float halfH = std::max(0.0f, (aabb.maxY - aabb.minY) * 0.5f);
      53       640772 :                 aabb.minX = tf->x - halfW;
      54       640772 :                 aabb.maxX = tf->x + halfW;
      55       640772 :                 aabb.minY = tf->y - halfH;
      56       640772 :                 aabb.maxY = tf->y + halfH;
      57              :             }
      58              :         }
      59              :     }
      60              : 
      61           41 :     PhysicsSystem::PhysicsSystem()
      62              :     {
      63           41 :         ApplySettings();
      64           41 :     }
      65              : 
      66         2492 :     void PhysicsSystem::Update(ecs::World& world, float dt)
      67              :     {
      68         2492 :         if (!std::isfinite(dt) || dt < 0.0f)
      69              :         {
      70            0 :             return;
      71              :         }
      72              : 
      73         2492 :         const int substeps = std::max(1, m_settings.substeps);
      74         2492 :         const float subDt = dt / static_cast<float>(substeps);
      75              : 
      76        31096 :         for (int i = 0; i < substeps; ++i)
      77              :         {
      78        28604 :             m_integration.Update(world, subDt);
      79        28604 :             SyncDynamicAabbsToTransforms(world);
      80              : 
      81        28604 :             m_events.clear();
      82        28604 :             m_broadphaseAABBs.clear();
      83        28604 :             m_broadphaseIds.clear();
      84              : 
      85        28604 :             auto* aabbStorage = world.GetStorage<AABBComponent>();
      86        28604 :             if (aabbStorage)
      87              :             {
      88        24123 :                 const auto& aabbs = aabbStorage->GetData();
      89        24123 :                 const auto& entities = aabbStorage->GetEntities();
      90              : 
      91        24123 :                 size_t count = aabbs.size();
      92        24123 :                 m_broadphaseAABBs.reserve(count);
      93        24123 :                 m_broadphaseIds.reserve(count);
      94              : 
      95        24123 :                 m_broadphaseAABBs.insert(m_broadphaseAABBs.end(), aabbs.begin(), aabbs.end());
      96        24123 :                 m_broadphaseIds.insert(m_broadphaseIds.end(), entities.begin(), entities.end());
      97              :             }
      98              : 
      99        28604 :             auto* circleStorage = world.GetStorage<CircleColliderComponent>();
     100        28604 :             auto* tfStorage = world.GetStorage<TransformComponent>();
     101        28604 :             if (circleStorage && tfStorage)
     102              :             {
     103        28538 :                 const auto& circles = circleStorage->GetData();
     104        28538 :                 const auto& entities = circleStorage->GetEntities();
     105        28538 :                 const size_t count = circles.size();
     106              : 
     107        28538 :                 m_broadphaseAABBs.reserve(m_broadphaseAABBs.size() + count);
     108        28538 :                 m_broadphaseIds.reserve(m_broadphaseIds.size() + count);
     109              : 
     110      1414461 :                 for (size_t j = 0; j < count; ++j)
     111              :                 {
     112      1385923 :                     const ecs::EntityId id = entities[j];
     113      1385923 :                     if (aabbStorage && aabbStorage->Get(id))
     114              :                     {
     115       120000 :                         continue;
     116              :                     }
     117              : 
     118      1265923 :                     auto* tf = tfStorage->Get(id);
     119      1265923 :                     if (!tf)
     120              :                     {
     121            0 :                         continue;
     122              :                     }
     123              : 
     124      1265923 :                     const auto& circle = circles[j];
     125      1265923 :                     const float radius = std::max(0.0f, circle.radius);
     126      1265923 :                     const float cx = tf->x + circle.offsetX;
     127      1265923 :                     const float cy = tf->y + circle.offsetY;
     128      1265923 :                     m_broadphaseAABBs.push_back({cx - radius, cy - radius, cx + radius, cy + radius});
     129      1265923 :                     m_broadphaseIds.push_back(id);
     130              :                 }
     131              :             }
     132              : 
     133        28604 :             if (!m_broadphaseAABBs.empty())
     134              :             {
     135        28604 :                 m_collision.Detect(m_broadphaseAABBs, m_broadphaseIds, m_events, m_jobSystem);
     136              :             }
     137              : 
     138        28604 :             if (!m_events.empty()) {
     139        28472 :                 m_resolution.ResolvePosition(m_events, world, m_jobSystem);
     140              :             }
     141              : 
     142        28604 :             m_constraints.Resolve(world, subDt);
     143        28604 :             m_integration.UpdateVelocities(world, subDt);
     144              : 
     145        28604 :             if (!m_events.empty()) {
     146        28472 :                 m_resolution.ResolveVelocity(m_events, world, m_jobSystem);
     147              :             }
     148              :         }
     149              :     }
     150              : 
     151           38 :     void PhysicsSystem::SetSettings(const PhysicsSettings& settings)
     152              :     {
     153           38 :         m_settings = settings;
     154           38 :         ApplySettings();
     155           38 :     }
     156              : 
     157           79 :     void PhysicsSystem::ApplySettings()
     158              :     {
     159           79 :         CollisionResolutionSystem::SolverSettings solver{};
     160           79 :         solver.positionIterations = m_settings.positionIterations;
     161           79 :         solver.velocityIterations = m_settings.velocityIterations;
     162           79 :         solver.penetrationSlop = m_settings.penetrationSlop;
     163           79 :         solver.correctionPercent = m_settings.correctionPercent;
     164           79 :         solver.maxCorrection = m_settings.maxPositionCorrection;
     165           79 :         m_resolution.SetSolverSettings(solver);
     166           79 :         m_constraints.SetIterationCount(m_settings.constraintIterations);
     167           79 :     }
     168              : }
        

Generated by: LCOV version 2.0-1