Repository navigation
Fix crashes, rework physics, and add tests, CI, tools and a demo - #1
Merged
Merged
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CSbmWwU5zh3ujWmjioWg1a
- World no longer deletes ForceGenerator components; entities own them. Removing a generator only unregisters it if it is the active one. - World::remove now removes the rigidbody from the spatial hash grid, fixing a use-after-free when a body is killed near another body. - Static bodies refresh their grid registration when moved by game code. - Scene teardown deletes entities before the systems they unregister from. - Window resets its stop flag on start, deletes the scene, shaders, picking framebuffer and ImGui context on shutdown, and no longer reads a pixel back from the GPU every frame. - DebugDraw allocated MAX_LINES times too much GPU memory. - Rigidbody: integrate angular velocity with the moment of inertia, use each collider's mass in the parallel axis term, compute bounds without always including the origin, and drop force registrations in clearForceGenerators. - Begin-down key/mouse queries now last for one frame instead of being consumed by the first reader. - Entity tolerates having no active scene; define Entity::setId. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CSbmWwU5zh3ujWmjioWg1a
Collision detection - Box/box now uses a separating axis test with reference face clipping. The old corner-containment test missed edge overlaps, so identical boxes stacked on each other fell straight through. - Circle/box finds the closest point on the box and handles circles whose centre has entered the box. - All features report the full penetration depth with the normal from the first collider to the second. Solver - Correct positions once per step after the impulse iterations, rather than re-applying the correction in every iteration. - Guard against NaN when contacts are touching with zero depth. - Cap the number of fixed steps per frame and drop excess time. - World gravity (previously an unused constructor argument) is applied to every dynamic body, scaled by a new per-body gravityScale. Raycasts - Box raycasts use a slab test in the box's local space (the old code ignored the ray entirely). Circles behind the ray are no longer hit, and normals point out of the surface. - World::raycast(ray, maxDistance) walks the spatial hash grid cells along the ray instead of testing every body. Ownership - Rigidbodies and force generators remember the World they were added to, so they unregister from the right world and work outside of a running scene. - Rigidbody::load reads colliders before velocity and force, which were previously dropped because a body without colliders has no mass. Debug drawing - Physics debug drawing (bounds, colliders, contacts) is off by default and toggled with World::setDebugDraw. DebugDraw can be disabled entirely with DebugDraw::setEnabled. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CSbmWwU5zh3ujWmjioWg1a
- Scene keeps its (previously unused) entity spatial hash grid in sync and offers getEntitiesIn, getEntitiesNear and getEntitiesAt. - Scene files store world gravity and restore the scene name, read audio from the "audio" key instead of "fonts", and report missing files correctly. - The console parses arguments and supports help, quit, clear, reset, save, load, debug, gravity, entities and inspector. Games can add their own with Console::registerCommand, and run commands with Console::execute. - New Inspector window: click an entity in the game to select it and edit its components, or pick it from the entity list. It also edits scene gravity and physics debug drawing. - Pancake::gravity, Pancake::debug and Pancake::inspector facade calls. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CSbmWwU5zh3ujWmjioWg1a
The previous solver averaged impulses across contacts and added a heuristic linear velocity, and the step integrated positions before solving contacts, so resting bodies sank every step and relied on position correction. A five row pyramid collapsed within seconds. - Step order is now: forces, integrate velocities, detect, solve, integrate positions, correct positions. - Contacts accumulate and clamp normal and friction impulses, and are warm started from a cache of last step's impulses. - Pairs are ordered by body id so results don't depend on memory layout. - Bounces below 1 unit per second are ignored to stop resting jitter. - Fixed orientation bodies get no rotational response. - Rigidbody gets an inspector panel. - Entity::addRotationAround compared the pivot to the world origin rather than the entity's own position. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CSbmWwU5zh3ujWmjioWg1a
- Pancake::size set width and height with two resizes, the second using a stale width. Before start the size is now used at creation, and at runtime both dimensions are applied together. - The viewport and picking framebuffer follow the framebuffer size, which differs from the window size on high DPI displays. readPixel converts window coordinates to pixels. - The console and inspector open in opposite corners. - Fall back to the default font if a font file cannot be read. - Remove unused variables and make shader sources constexpr. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CSbmWwU5zh3ujWmjioWg1a
- tests/: a minimal test harness and unit tests for the spatial grid, collision detection, the solver (resting, stacking, pyramids, angled drops), force generators, raycasts and JSON round trips, plus an engine test that runs the real loop to check saving, reloading, killing bodies, resetting scenes with force generators and console commands. - CMake: C++17 is required explicitly, AddressSanitizer moved behind PANCAKE_ASAN (it was always linked into games on Linux), and PANCAKE_BUILD_TESTS / PANCAKE_BUILD_EXAMPLES default on only when Pancake is the top level project. - GitHub Actions builds with ASan and in Release, and runs all tests under Xvfb. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CSbmWwU5zh3ujWmjioWg1a
Spawns boxes and balls, pans and zooms the camera, and binds keys to the console, inspector and physics debug drawing. --frames N quits after N frames, which CTest uses as a smoke test of the whole engine. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CSbmWwU5zh3ujWmjioWg1a
Document building the engine on its own, the tests and options, the debugging tools, and upgrade notes for world gravity, the new solver and per-frame input queries. Fix the README example, which never fell because nothing applied gravity, and drop the gamepad claim as there is no gamepad support. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CSbmWwU5zh3ujWmjioWg1a
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.
Picks the engine up from where the force-generator refactor left it in August 2024. This fixes the memory bugs that refactor introduced and makes the physics hold up for normal game scenes. It also adds tests and CI, finishes the half-built features, and adds a demo sandbox.
Memory-safety fixes
Gravitycomponent caused a heap-use-after-free, becauseWorlddeleted force generator components that their entities also deleted. Entities now own them; the world only registers them.stop().Physics
gravityScale.World::raycast(ray, maxDistance)walks the grid.Engine and tools
getEntitiesIn/Near/At.audio(it readfonts), and keep rigidbody velocity on load.help,save,load,reset,debug,gravity,entities,inspector), plusConsole::registerCommandandConsole::execute.Pancake::sizesets the correct size, and the viewport follows the framebuffer size on high-DPI displays.glReadPixelscall.Build, tests and CI
PANCAKE_ASAN; it was always linked into games on Linux.PANCAKE_BUILD_TESTSandPANCAKE_BUILD_EXAMPLESdefault to on only when Pancake is the top-level project.examples/demo.cppis a physics sandbox.Behaviour changes for existing games
These are also listed under "Upgrading" in the README.
(0, -10). A game that added aGravitycomponent to get global gravity should remove it or set the world gravity to zero.isKeyBeginDownandisMouseBeginDownnow stay true for the whole frame.Testing
🤖 Generated with Claude Code
https://claude.ai/code/session_01CSbmWwU5zh3ujWmjioWg1a
Generated by Claude Code