Repository navigation
Conversation
…eries Pairs are collected first and resolved second with fresh poses. Triggers no longer push, dynamic pairs split the correction by inverse mass, and touching pairs are tracked across steps to send OnCollision/OnTrigger Enter/Stay/Exit to every component on both objects. Raycast walks the tree's ray query and tests the actual shapes; the overlap queries do a narrowphase and return OverlapHit. Colliders cache their rigidbody and transform keyed on a new GameObject component version.
5 tasks done
… feat/physics-contacts-and-queries # Conflicts: # src/Physics/PhysicsWorld.cpp
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this changes
Stacked on #197 (it touches the same
PhysicsWorld::Step), so the diff againstfix/physics-fixed-timestepis the part to review.PhysicsWorld::Stepis split into integrate, broadphase, collect pairs, resolve, dispatch. Pairs are collected from the tree first (only pairs where at least one side has a non-static rigidbody), then each one gets its narrowphase against the current poses and is resolved:RigidbodyComponentdoc already promisedTouching pairs are kept in a list sorted by proxy id pair and diffed against the previous step's, and the result goes out as new
Componentvirtuals:OnCollisionEnter/Stay/Exitfor solid pairs,OnTriggerEnter/Stay/Exitwhen either side is a trigger, sent to every component on both objects with aPhysics::CollisionEvent(self, other, point, normal pointing from self to other, penetration). A callback can remove or destroy objects, its own included; the world notices and skips whatever is gone.Raycastnow usesDynamicAABBTree::RayCastas the broadphase and tests the real shape: slab for boxes, ray vs sphere, ray vs capsule (cylinder body plus the two cap spheres), and ray vs triangle mesh done in the mesh's local space so a scaled mesh is not copied per ray. It returns the exact point, surface normal and distance in world units, takes an unnormalized direction, and skips colliders that contain the origin (so a ray cast from inside the player's own collider does not hit the player). The shape tests are public inCollisionDetection.hpp(RaycastAABB/Sphere/Capsule/Triangle/Shape).OverlapSphereandOverlapAABBrunTestCollisionon every broadphase candidate and returnstd::vector<OverlapHit>(collider, point, normal, penetration) instead ofCollisionPairs witha == nullptrand an empty manifold.ColliderComponentcaches its rigidbody, transform and camera, keyed on a newGameObject::GetComponentVersion()thatAddComponent/RemoveComponentbump, so a step no longer runsGetComponent(adynamic_castper component) several times per collider and per pair, and a removed rigidbody can never leave a dangling cached pointer.GameObject::GetComponents()is new for the callback dispatch.RigidbodyComponent::ApplyContactNormalis the velocity and ground/wall half ofResolveCollisionso the world can move the body through the cached transform.PhysicsWorldandDynamicAABBTreegetENGINE_API.Why
Triggers: the old loop only skipped pairs where both colliders were triggers, so trigger vs dynamic fell through to
ResolveCollisionand shoved the body out of the volume, while theColliderComponentdoc shows a pickup volume that "never pushes". The manifold was also thrown away on every path, so a trigger could not report anything either.Double separation: both sides of a dynamic pair got
ResolveCollision(normal, penetration)with the full penetration and translated by it, so two bodies ended up twice as far apart as needed and popped. Mass was stored and never read.Raycast was
SphereSweep(origin, direction, 0.01f, ...), which tests the ray against each collider's world AABB grown by 1cm. Every sphere and capsule was hit as its bounding box, grazing rays hit things a ray misses, and the normal was guessed from which side of the box center the point was on.DynamicAABBTree::RayCastexisted and nothing called it.Fixes #11
Fixes #12
Fixes #17
Fixes #24
Not covered here:
SphereSweepis still the fattened AABB approximation. Capsule vs mesh and mesh vs mesh still have no narrowphase (pre-existing,TestCollisionreturns no hit), so those pairs neither resolve nor report. Static vs static pairs are no longer tested at all, which also means no callbacks between two static colliders. A pair whose collider is unregistered (object removed or destroyed) ends silently, no Exit, so user code never runs against an object that is being deleted. SleakCraft does not touch any of this: its player has the only collider in the scene and resolves against voxels itself, which I did not change.How it was verified
SleakCraft built against this branch and ran under xvfb on Mesa llvmpipe (
-r opengl -world citest -seed 42 -rd 4) for 90s: world created, no errors, survived to the timeout. Also repeated the temporary grounded/jump logging from #197 here, same result (grounded on all but the first couple of frames, jump peak 1.033m).Throwaway harness with the five physics sources compiled in under ASan and UBSan, the rest linked from
libEngined.so, driving aScenesubclass:The ball falls through the trigger zone with zero sideways drift (the zone used to push it out), the dynamic pair separates by exactly the penetration split 1:3, and the grazing ray at 0.505 now misses the 0.5 sphere instead of hitting its padded box.
Checklist
///commentssrc/orinclude/private/in public headers