Skip to content

feat(physics): mesh collider#439

Merged
Divengerss merged 8 commits into
mainfrom
mesh-collider
Jan 25, 2026
Merged

feat(physics): mesh collider#439
Divengerss merged 8 commits into
mainfrom
mesh-collider

Conversation

@ripel2
Copy link
Copy Markdown
Contributor

@ripel2 ripel2 commented Jan 25, 2026

Not related to any issues.

Add support form mesh colliders using Jolt's ConvexHullShape.

The "DefaultCollider" was useless and was remove. Instead, if a user doesn't add any collider, a mesh collider will be used by default.
Existing colliders (Box, Sphere) can still be used, they are a lot less expensive for simple shapes than full mesh colliders.
See the updated physics example (with graphics) for more detail

Summary by CodeRabbit

  • New Features

    • Added a MeshCollider component for explicit mesh-based collision with adjustable precision.
  • Documentation

    • Clarified collider docs to state colliders override automatic mesh-based collision.
    • Updated examples to show automatic convex-hull generation from meshes and an explicit MeshCollider usage example.
  • Refactor

    • Simplified component constructors to remove redundant engine-core arguments; removed chassis half-extents setter from vehicle builder.
  • Tests

    • Streamlined physics test setup by consolidating collider additions.

✏️ Tip: You can customize this high-level summary in your review settings.

@ripel2 ripel2 requested a review from a team January 25, 2026 10:55
@ripel2 ripel2 self-assigned this Jan 25, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 25, 2026

Warning

Rate limit exceeded

@ripel2 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 13 minutes and 21 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📝 Walkthrough

Walkthrough

This PR adds a MeshCollider component, replaces DefaultCollider usage with MeshCollider across the physics system, updates RigidBodySystem to generate ConvexHullShape colliders from mesh geometry when appropriate, and updates examples, vehicle builder, and collider docs to reflect the new mesh-first collider behavior.

Changes

Cohort / File(s) Summary
Example Documentation Updates
examples/graphic_usage_with_physics/src/main.cpp, examples/physics_usage/src/main.cpp
Updated comments to explain automatic collision shape creation from mesh vertices; added commented example of explicit MeshCollider creation and notes on maxConvexRadius.
Physics System Includes
src/plugin/physics/src/Physics.hpp
Replaced include of component/DefaultCollider.hpp with component/MeshCollider.hpp.
Collider Component Documentation
src/plugin/physics/src/component/BoxCollider.hpp, src/plugin/physics/src/component/CapsuleCollider.hpp, src/plugin/physics/src/component/SphereCollider.hpp
Updated docs to state colliders override automatic mesh-based collision (language changes only).
New MeshCollider Component
src/plugin/physics/src/component/MeshCollider.hpp
Added MeshCollider struct with float maxConvexRadius (default 0.05f) and constructors to configure convex radius.
Vehicle Chassis Configuration
src/plugin/physics/src/builder/VehicleBuilder.hpp
Replaced chassis BoxCollider and removed SetChassisHalfExtents(...) API; chassis now uses MeshCollider.
Collision Shape Selection Logic
src/plugin/physics/src/system/RigidBodySystem.cpp
Replaced DefaultCollider path with MeshCollider handling; added CreateConvexHullFromMesh helper and ConvexHullShape creation from mesh vertices; updated shape selection priority (Sphere → Capsule → Box → Mesh).
Example / Scene API usage
examples/vehicle_usage/src/main.cpp, examples/vehicle_usage/src/scenes/VehicleScene.cpp
Removed Engine::Core parameter from Transform and Camera component constructors and related AddComponent calls; removed SetChassisHalfExtents usage in scene setup.
Tests
src/plugin/physics/tests/PhysicsTest.cpp
Consolidated BoxCollider additions: add colliders before rigid bodies for plane and cube (reordered/cleanup).

Sequence Diagram(s)

sequenceDiagram
    participant S as RigidBodySystem
    participant E as Entity (Components)
    participant Mesh as Object::Mesh
    participant Colliders as Collider Components
    participant J as Physics Engine (Jolt)

    S->>E: Inspect components (RigidBody + colliders + mesh)
    alt Sphere present
        S->>J: Create SphereShape
    else alt Capsule present
        S->>J: Create CapsuleShape
    else alt Box present
        S->>J: Create BoxShape
    else alt MeshCollider present
        S->>Mesh: Extract vertices
        S->>J: Create ConvexHullShape (use MeshCollider.maxConvexRadius)
    else alt Mesh present (no collider)
        S->>Mesh: Extract vertices
        S->>J: Create ConvexHullShape (default config)
    else
        S->>S: Log warning (no collider/mesh)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • Miou-zora

Poem

🐇 A tiny rabbit hops and sings,
Meshes turned to convex things,
Colliders shaped from vertex art,
Physics hops forward — smart! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 78.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(physics): mesh collider' directly and clearly describes the main change: adding mesh collider support to the physics system.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/plugin/physics/src/component/BoxCollider.hpp (1)

37-42: Documentation example may have incorrect API signature.

Same issue as in MeshCollider.hpp - the example shows AddComponent with two arguments, but actual usage in examples shows single-argument calls.

Proposed fix
 * `@code`
 * Physics::Component::BoxCollider collider;
 * collider.halfExtents = glm::vec3(0.5f, 1.0f, 0.5f);
-* entity.AddComponent<Physics::BoxCollider>(core, collider);
+* entity.AddComponent<Physics::Component::BoxCollider>(collider);
 * `@endcode`
src/plugin/physics/src/component/CapsuleCollider.hpp (1)

55-61: Documentation example may have incorrect API signature.

Consistent with the other collider headers, the example uses two-argument AddComponent while actual usage appears to use single-argument calls.

Proposed fix
 * `@code`
 * Physics::Component::CapsuleCollider collider;
 * collider.halfHeight = 0.8f;  // Cylinder part is 1.6m tall
 * collider.radius = 0.3f;      // Total height = 1.6 + 0.6 = 2.2m
-* entity.AddComponent<Physics::Component::CapsuleCollider>(core, collider);
+* entity.AddComponent<Physics::Component::CapsuleCollider>(collider);
 * `@endcode`
🤖 Fix all issues with AI agents
In `@src/plugin/physics/src/builder/VehicleBuilder.hpp`:
- Line 212: The chassis was switched to a MeshCollider via
chassis.AddComponent<Component::MeshCollider>() which makes _chassisHalfExtents
and SetChassisHalfExtents() no-ops; update VehicleBuilder so
SetChassisHalfExtents() either (a) switches the chassis collider to a
BoxCollider and sets its extents (e.g., replace or add Component::BoxCollider to
the chassis when SetChassisHalfExtents is called), or (b) mark
SetChassisHalfExtents() deprecated/removed and add a new explicit API (e.g.,
SetChassisAsBox / UseBoxCollider) that adds Component::BoxCollider with the
provided extents while leaving MeshCollider as the default; ensure references to
chassis.AddComponent<Component::MeshCollider>(), _chassisHalfExtents, and
SetChassisHalfExtents() are updated accordingly and that behavior is
documented/covered by tests.
- Line 212: VehicleBuilder.hpp uses Component::MeshCollider in the call
chassis.AddComponent<Component::MeshCollider>() but does not include its header;
add the MeshCollider header include at the top of VehicleBuilder.hpp (e.g.,
include the MeshCollider declaration header such as "Component/MeshCollider.hpp"
or the project's corresponding header that defines Component::MeshCollider) so
the symbol is available for compilation.

In `@src/plugin/physics/src/component/MeshCollider.hpp`:
- Around line 44-53: The documentation example for MeshCollider uses the wrong
Entity::AddComponent signature by passing `core` explicitly; update the example
so calls to AddComponent match the actual API used elsewhere: call
entity.AddComponent<Physics::Component::MeshCollider>(collider) and
entity.AddComponent<Physics::Component::RigidBody>(rigidBody) (i.e., remove the
`core` argument) while keeping the same MeshCollider and RigidBody symbols and
descriptive comments.

In `@src/plugin/physics/src/system/RigidBodySystem.cpp`:
- Around line 32-68: CreateConvexHullFromMesh currently builds the hull from raw
mesh vertices without applying the entity Transform scale; update the function
signature (CreateConvexHullFromMesh) to accept a glm/Jolt-compatible scale
parameter (e.g., Vec3 scale), multiply each vertex by that scale before
converting with Utils::ToJoltVec3, and use the scaled joltPoints to construct
ConvexHullShapeSettings; also update the caller (CreateShapeFromColliders) to
pass the Transform's scale from the registry when invoking
CreateConvexHullFromMesh.
🧹 Nitpick comments (1)
src/plugin/physics/src/system/RigidBodySystem.cpp (1)

152-153: Add more context to the error log.

The new error is a helpful guard, but it would be more actionable if it included the entity id (and possibly the mesh presence/vertex count) for faster debugging.

Comment thread src/plugin/physics/src/builder/VehicleBuilder.hpp
Comment thread src/plugin/physics/src/component/MeshCollider.hpp Outdated
Comment on lines +32 to +68
/**
* @brief Create a ConvexHullShape from mesh vertices
* @param mesh The mesh component containing vertices
* @param meshCollider Mesh collider settings (convex radius)
* @return RefConst to the created shape, or nullptr on failure
*/
static JPH::RefConst<JPH::Shape> CreateConvexHullFromMesh(const Object::Component::Mesh &mesh,
const Component::MeshCollider &meshCollider)
{
const auto &vertices = mesh.GetVertices();

if (vertices.empty())
{
Log::Warn("MeshCollider: Mesh has no vertices, cannot create convex hull");
return nullptr;
}

JPH::Array<JPH::Vec3> joltPoints;
joltPoints.reserve(vertices.size());

for (const auto &vertex : vertices)
{
joltPoints.push_back(Utils::ToJoltVec3(vertex));
}

float maxConvexRadius = meshCollider.maxConvexRadius;
JPH::ConvexHullShapeSettings settings(joltPoints, maxConvexRadius);

JPH::ShapeSettings::ShapeResult result = settings.Create();
if (!result.IsValid())
{
Log::Error(fmt::format("MeshCollider: Failed to create convex hull shape: {}", result.GetError().c_str()));
return nullptr;
}

return result.Get();
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, run the provided search to find Mesh component and GetVertices
rg -n "class Mesh|struct Mesh|GetVertices" -g '*.hpp' -g '*.cpp' | head -50

Repository: EngineSquared/EngineSquared

Length of output: 4352


🏁 Script executed:

# Examine the Mesh component definition
cat -n src/plugin/object/src/component/Mesh.hpp | head -100

Repository: EngineSquared/EngineSquared

Length of output: 3811


🏁 Script executed:

# Find where CreateConvexHullFromMesh is called in RigidBodySystem
rg -n "CreateConvexHullFromMesh" src/plugin/physics/src/system/RigidBodySystem.cpp -A 5 -B 5

Repository: EngineSquared/EngineSquared

Length of output: 951


🏁 Script executed:

# Get more context around the call site to understand the function signature
sed -n '100,145p' src/plugin/physics/src/system/RigidBodySystem.cpp

Repository: EngineSquared/EngineSquared

Length of output: 1985


🏁 Script executed:

# Get the function signature that contains the CreateConvexHullFromMesh call
sed -n '70,145p' src/plugin/physics/src/system/RigidBodySystem.cpp

Repository: EngineSquared/EngineSquared

Length of output: 3232


🏁 Script executed:

# Check how SoftBodySystem uses scale with mesh vertices
sed -n '200,220p' src/plugin/physics/src/system/SoftBodySystem.cpp

Repository: EngineSquared/EngineSquared

Length of output: 1052


🏁 Script executed:

# Find the SoftBodySystem function signature that uses scale
sed -n '150,220p' src/plugin/physics/src/system/SoftBodySystem.cpp

Repository: EngineSquared/EngineSquared

Length of output: 2915


🏁 Script executed:

# Find where CreateJoltSharedSettings is called to see if scale is passed
rg -n "CreateJoltSharedSettings" src/plugin/physics/src/system/SoftBodySystem.cpp -B 2 -A 2

Repository: EngineSquared/EngineSquared

Length of output: 659


🏁 Script executed:

# Find the function that calls CreateJoltSharedSettings at line 422
sed -n '380,430p' src/plugin/physics/src/system/SoftBodySystem.cpp

Repository: EngineSquared/EngineSquared

Length of output: 2190


🏁 Script executed:

# Check if RigidBodySystem applies scale elsewhere, or how rigid bodies use the created shapes
rg -n "GetOrCreateColliderShape\|CreateShapeFromColliders" src/plugin/physics/src/system/RigidBodySystem.cpp -A 10 | head -60

Repository: EngineSquared/EngineSquared

Length of output: 53


🏁 Script executed:

# Search for where shapes are used with Transform in RigidBodySystem
rg -n "GetOrCreateColliderShape\|CreateShape" src/plugin/physics/src/system/RigidBodySystem.cpp

Repository: EngineSquared/EngineSquared

Length of output: 53


🏁 Script executed:

# Look for all usages of Transform in RigidBodySystem to see if scale is applied anywhere
rg -n "Transform\|scale" src/plugin/physics/src/system/RigidBodySystem.cpp | head -50

Repository: EngineSquared/EngineSquared

Length of output: 53


🏁 Script executed:

# Get the full RigidBodySystem.cpp to understand the complete picture
wc -l src/plugin/physics/src/system/RigidBodySystem.cpp

Repository: EngineSquared/EngineSquared

Length of output: 124


🏁 Script executed:

# Read the entire RigidBodySystem.cpp
cat -n src/plugin/physics/src/system/RigidBodySystem.cpp

Repository: EngineSquared/EngineSquared

Length of output: 12795


Convex hull ignores Transform scale—mesh vertices need to be scaled during shape creation.

The mesh vertices are stored raw (not scale-baked) in the Mesh component. When CreateConvexHullFromMesh builds the convex hull, it does not apply the entity's Transform scale, resulting in incorrect physics geometry size. The SoftBodySystem already establishes the pattern of passing scale to mesh-based shape creation (see CreateJoltSharedSettings).

Pass the scale from the Transform to CreateConvexHullFromMesh and apply it to vertices:

🔧 Example adjustment
-static JPH::RefConst<JPH::Shape> CreateConvexHullFromMesh(const Object::Component::Mesh &mesh,
-                                                          const Component::MeshCollider &meshCollider)
+static JPH::RefConst<JPH::Shape> CreateConvexHullFromMesh(const Object::Component::Mesh &mesh,
+                                                          const Component::MeshCollider &meshCollider,
+                                                          const glm::vec3 &scale)
 {
     const auto &vertices = mesh.GetVertices();
@@
     for (const auto &vertex : vertices)
     {
-        joltPoints.push_back(Utils::ToJoltVec3(vertex));
+        joltPoints.push_back(Utils::ToJoltVec3(vertex * scale));
     }

Then call it with the Transform's scale in CreateShapeFromColliders where the Transform is available via the registry.

🤖 Prompt for AI Agents
In `@src/plugin/physics/src/system/RigidBodySystem.cpp` around lines 32 - 68,
CreateConvexHullFromMesh currently builds the hull from raw mesh vertices
without applying the entity Transform scale; update the function signature
(CreateConvexHullFromMesh) to accept a glm/Jolt-compatible scale parameter
(e.g., Vec3 scale), multiply each vertex by that scale before converting with
Utils::ToJoltVec3, and use the scaled joltPoints to construct
ConvexHullShapeSettings; also update the caller (CreateShapeFromColliders) to
pass the Transform's scale from the registry when invoking
CreateConvexHullFromMesh.

@sonarqubecloud
Copy link
Copy Markdown

@Divengerss Divengerss merged commit 0b50fb1 into main Jan 25, 2026
15 checks passed
@Divengerss Divengerss deleted the mesh-collider branch January 25, 2026 13:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants