From 1a0fb87b93ead2b642accb8aa198a06c78a2a773 Mon Sep 17 00:00:00 2001 From: Sergey Lapin Date: Mon, 25 May 2026 04:19:03 +0300 Subject: [PATCH] some docs --- buoyancy_analysis.md | 217 ++++++++++++++++++++++++++++++++++++++ buoyancy_debug_summary.md | 172 ++++++++++++++++++++++++++++++ 2 files changed, 389 insertions(+) create mode 100644 buoyancy_analysis.md create mode 100644 buoyancy_debug_summary.md diff --git a/buoyancy_analysis.md b/buoyancy_analysis.md new file mode 100644 index 0000000..e2053cd --- /dev/null +++ b/buoyancy_analysis.md @@ -0,0 +1,217 @@ +# Buoyancy System Analysis + +## Problem: Characters are not affected by buoyancy + +After analyzing the code in `src/features/editScene`, I've identified several potential issues: + +## 1. Character Gravity Factor Issue + +**Root Cause**: Characters have gravity factor set to 0.0f by default. + +In `CharacterSystem.cpp` line 163: +```cpp +m_physics->setGravityFactor(ch->GetBodyID(), 0.0f); +``` + +This means characters won't sink into water naturally. The `BuoyancySystem` tries to handle this by setting gravity factor to 1.0f when characters are in water (line 127 in `BuoyancySystem.cpp`), but there may be timing or detection issues. + +## 2. Broadphase Query Area Settings + +The `broadphaseQuery` function in `physics.cpp` uses these settings: + +```cpp +JPH::AABox water_box(-JPH::Vec3(1000, 1000, 1000), + JPH::Vec3(1000, 0.1f, 1000)); +water_box.Translate(JPH::Vec3(surface_point)); +``` + +Where `surface_point = position + Ogre::Vector3(0, -0.1f, 0)` (position is the water surface Y level). + +**Dimensions**: +- X: -1000 to 1000 (2000 units wide, centered at surface_point.x) +- Y: -1000 to 0.1f (1000.1 units tall, but centered 0.1 units BELOW water surface) +- Z: -1000 to 1000 (2000 units deep, centered at surface_point.z) + +**Issue**: The water box extends 1000 units BELOW the surface point, but only 0.1 units ABOVE it. Since `surface_point` is 0.1 units below the actual water surface, the box effectively covers: +- From 1000.1 units below water surface +- To 0.0 units at water surface (not above it) + +This means bodies need to be at or below the water surface to be detected. + +## 3. Character Detection in Broadphase + +Characters are `JPH::Character` objects, not regular dynamic bodies. The broadphase query filters for: +- `BroadPhaseLayers::MOVING` layer +- `Layers::MOVING` object layer + +Characters should be in these layers, but there may be issues with how character bodies are registered in the broadphase. + +## 4. Debugging Approach + +### 4.1 Enable Debug Logging + +Modify `BuoyancySystem.cpp` to add debug logging: + +```cpp +// In update() method, after broadphaseQuery call: +Ogre::LogManager::getSingleton().logMessage( + "BuoyancySystem: Found " + Ogre::StringConverter::toString(m_bodiesInWater.size()) + + " bodies in water"); + +// In the loop applying buoyancy: +for (JPH::BodyID bodyID : m_bodiesInWater) { + Ogre::SceneNode *node = m_physics->getSceneNodeFromBodyID(bodyID); + if (node) { + Ogre::LogManager::getSingleton().logMessage( + "Body " + Ogre::StringConverter::toString(bodyID.GetIndex()) + + " at position: " + Ogre::StringConverter::toString(m_physics->getPosition(bodyID))); + } + + // Check if it's a character + if (m_physics->bodyIsCharacter(bodyID)) { + Ogre::LogManager::getSingleton().logMessage( + "Body " + Ogre::StringConverter::toString(bodyID.GetIndex()) + " is a character"); + } +} +``` + +### 4.2 Visual Debugging - Draw Water Box + +Add debug rendering to visualize the water detection area: + +```cpp +// In BuoyancySystem::update(), after broadphaseQuery: +void drawDebugWaterBox(const Ogre::Vector3& waterSurfacePos) { + // Create a manual object to visualize the water box + static Ogre::ManualObject* waterBoxDebug = nullptr; + if (!waterBoxDebug) { + waterBoxDebug = m_sceneManager->createManualObject("WaterBoxDebug"); + Ogre::SceneNode* debugNode = m_sceneManager->getRootSceneNode()->createChildSceneNode(); + debugNode->attachObject(waterBoxDebug); + } + + waterBoxDebug->clear(); + waterBoxDebug->begin("BaseWhiteNoLighting", Ogre::RenderOperation::OT_LINE_LIST); + + // Water box dimensions (matching broadphaseQuery) + float halfSize = 1000.0f; + float top = waterSurfacePos.y - 0.1f + 0.1f; // surface_point.y + 0.1f + float bottom = waterSurfacePos.y - 0.1f - 1000.0f; // surface_point.y - 1000.0f + + // Draw box edges + Ogre::Vector3 corners[8] = { + {waterSurfacePos.x - halfSize, bottom, waterSurfacePos.z - halfSize}, + {waterSurfacePos.x + halfSize, bottom, waterSurfacePos.z - halfSize}, + {waterSurfacePos.x + halfSize, bottom, waterSurfacePos.z + halfSize}, + {waterSurfacePos.x - halfSize, bottom, waterSurfacePos.z + halfSize}, + {waterSurfacePos.x - halfSize, top, waterSurfacePos.z - halfSize}, + {waterSurfacePos.x + halfSize, top, waterSurfacePos.z - halfSize}, + {waterSurfacePos.x + halfSize, top, waterSurfacePos.z + halfSize}, + {waterSurfacePos.x - halfSize, top, waterSurfacePos.z + halfSize} + }; + + // Bottom square + for (int i = 0; i < 4; i++) { + waterBoxDebug->position(corners[i]); + waterBoxDebug->position(corners[(i+1)%4]); + } + + // Top square + for (int i = 4; i < 8; i++) { + waterBoxDebug->position(corners[i]); + waterBoxDebug->position(corners[4 + (i-3)%4]); + } + + // Vertical edges + for (int i = 0; i < 4; i++) { + waterBoxDebug->position(corners[i]); + waterBoxDebug->position(corners[i+4]); + } + + waterBoxDebug->end(); +} +``` + +### 4.3 Check Character Position Relative to Water + +Add a debug function to check character positions: + +```cpp +void debugCharacterPositions() { + m_world.query().each( + [&](flecs::entity entity, CharacterComponent &cc, TransformComponent &transform) { + if (transform.node) { + Ogre::Vector3 worldPos = transform.node->_getDerivedPosition(); + Ogre::LogManager::getSingleton().logMessage( + "Character entity " + Ogre::StringConverter::toString(entity.id()) + + " at Y: " + Ogre::StringConverter::toString(worldPos.y)); + + // Check if character has physics body + auto it = m_states.find(entity.id()); + if (it != m_states.end() && it->second.character) { + JPH::BodyID bodyID = it->second.character->GetBodyID(); + Ogre::Vector3 bodyPos = m_physics->getPosition(bodyID); + Ogre::LogManager::getSingleton().logMessage( + "Character body at Y: " + Ogre::StringConverter::toString(bodyPos.y) + + ", gravity factor: " + Ogre::StringConverter::toString(m_physics->getGravityFactor(bodyID))); + } + } + }); +} +``` + +## 5. Recommended Fixes + +### 5.1 Adjust Water Box Parameters + +The current water box may be too shallow (only 0.1 units at the top). Consider adjusting: + +```cpp +// In broadphaseQuery function: +JPH::AABox water_box(-JPH::Vec3(1000, 1.0f, 1000), // Increased from 0.1f to 1.0f + JPH::Vec3(1000, 1000, 1000)); // Symmetrical above/below +``` + +This creates a 2-unit tall detection area centered on the surface point. + +### 5.2 Fix Character Gravity Handling + +Modify `BuoyancySystem::update()` to better handle character gravity: + +```cpp +// Current issue: characters with gravity factor 0 won't sink into water +// Even if buoyancy is applied, they need gravity to sink first + +// Potential fix: Always give characters some minimal gravity when near water +// or modify CharacterSystem to not set gravity factor to 0 +``` + +### 5.3 Verify Character Body Registration + +Ensure character bodies are properly registered in the physics system and included in broadphase queries. Check that: +1. Characters are added to the physics system (`ch->AddToPhysicsSystem()`) +2. They are in the `MOVING` broadphase layer +3. Their body IDs are valid for queries + +## 6. Testing Procedure + +1. **Enable debug logging** as shown above +2. **Place a character in water** (Y position below water surface) +3. **Check console output** for: + - Number of bodies detected in water + - Character body positions + - Gravity factor changes +4. **Use visual debug** to see water box +5. **Adjust water surface Y** in WaterPhysics component to ensure it's above character position + +## 7. Water Physics Settings + +Default `WaterPhysics` component has: +- `waterSurfaceY = -0.1f` (slightly below origin) +- `defaultBuoyancy = 1.0f` (neutral buoyancy) +- `enabled = true` + +Make sure: +1. WaterPhysics entity exists (BuoyancySystem creates one if missing) +2. `waterSurfaceY` is above character positions for testing +3. Water physics is enabled (`enabled = true`) \ No newline at end of file diff --git a/buoyancy_debug_summary.md b/buoyancy_debug_summary.md new file mode 100644 index 0000000..876d958 --- /dev/null +++ b/buoyancy_debug_summary.md @@ -0,0 +1,172 @@ +# Buoyancy System Analysis and Debugging Guide + +## Problem Analysis + +After analyzing the buoyancy system in `src/features/editScene`, I identified several key issues why characters are not affected by buoyancy: + +### 1. **Broadphase Query Area Not Following Camera** +The original buoyancy system used a fixed position `(0, waterSurfaceY, 0)` for the broadphase query AABox. This meant the water detection area was static at world origin, not following the camera or characters. + +**Fix Applied**: Modified `BuoyancySystem::update()` to use camera XZ position with water Y position: +```cpp +Ogre::Vector3 waterSurfacePos(m_cameraPosition.x, waterPhysics->waterSurfaceY, m_cameraPosition.z); +``` + +### 2. **Character Physics Layer Issue** +Characters are created with `Layers::MOVING` but the broadphase query in `physics.cpp` was checking for bodies in specific layers. The query needs to include the MOVING layer. + +**Fix Applied**: Updated `broadphaseQuery` in `physics.cpp` to include `Layers::MOVING`: +```cpp +if (body->GetMotionType() == JPH::EMotionType::Dynamic && + (body->GetObjectLayer() == Layers::MOVING || + body->GetObjectLayer() == Layers::NON_MOVING)) { +``` + +### 3. **Character Gravity Factor Management** +Characters have gravity factor 0 by default (to prevent sinking into terrain). When they enter water, we need to: +1. Save original gravity factor +2. Set gravity factor to 1.0 to allow sinking +3. Restore original gravity when leaving water + +**Fix Applied**: Added gravity factor caching in `BuoyancySystem`: +```cpp +// Save original gravity factor if not already saved +if (m_characterOriginalGravity.find(bodyID) == m_characterOriginalGravity.end()) { + m_characterOriginalGravity[bodyID] = m_physics->getGravityFactor(bodyID); +} +// Enable gravity for characters in water so they sink +m_physics->setGravityFactor(bodyID, 1.0f); +``` + +### 4. **Water AABox Size Configuration** +The broadphase query uses an AABox centered at water surface position with size `(100, 10, 100)`. This may need adjustment based on your scene scale. + +## Debugging Approach + +### 1. **Enable Debug Logging** +Run the editor with the `--debug-buoyancy` command line option: +```bash +./build/Editor --debug-buoyancy +``` + +This enables verbose logging every 60 frames (about 1 second at 60 FPS) showing: +- Water physics state (surface Y, enabled, buoyancy) +- Camera position +- Water detection center position +- All characters and their positions +- Bodies detected in water by broadphase query +- Character gravity factor cache + +### 2. **Broadphase Query Settings** +The water detection area is configured in `src/features/editScene/physics/physics.cpp`: + +```cpp +// AABox for water detection (centered at water surface position) +// Box extends from (-1000, 1.0, -1000) to (1000, 1000, 1000) relative to surface +// Total size: 2000x999x2000 units +JPH::AABox water_box(-JPH::Vec3(1000, 1.0f, 1000), + JPH::Vec3(1000, 1000, 1000)); +water_box.Translate(JPH::Vec3(surface_point)); +``` + +**Current Filter Settings**: +- Only checks `Layers::MOVING` bodies (line 1587) +- Uses `BroadPhaseLayers::MOVING` filter (line 1586) + +**Adjustment Recommendations**: +1. **Check character layer**: Ensure characters are in `Layers::MOVING` +2. **Adjust box size**: The current 2000x999x2000 box is very large + - Reduce 1000 values for smaller detection area + - Adjust Y values (1.0f and 1000) for vertical detection range +3. **Add NON_MOVING layer**: If characters are in NON_MOVING layer, update filter: + ```cpp + JPH::SpecifiedObjectLayerFilter(Layers::MOVING | Layers::NON_MOVING) + ``` +4. **Box follows camera**: The box is translated to `surface_point` which now uses camera XZ position + +### 3. **Water Physics Configuration** +Default water settings (in `EditorApp::createDefaultEntities()`): +- `waterSurfaceY = -0.1f` (just below ground level) +- `defaultBuoyancy = 1.0f` (neutral buoyancy) +- `defaultLinearDrag = 0.1f` +- `defaultAngularDrag = 0.05f` +- `gravity = 9.81f` + +**To adjust**: Use the Water Physics editor UI or modify the WaterPhysics component. + +### 4. **Character Configuration** +Ensure characters: +1. Have `CharacterComponent` attached +2. Are in the `MOVING` physics layer +3. Have proper collision shapes +4. Are spawned at Y position below water surface for testing + +## Testing Procedure + +1. **Build the project**: +```bash +cmake --build build --target Editor +``` + +2. **Run with debug mode**: +```bash +./build/Editor --debug-buoyancy +``` + +3. **Create test scene**: + - Add water (WaterPhysics entity exists by default) + - Spawn characters (use Character spawner in UI) + - Position characters below water surface (Y < -0.1) + +4. **Monitor console output** for debug messages showing: + - "Bodies in water (broadphase): X" + - Character positions and "inWater" status + - Gravity factor changes + +5. **Adjust settings as needed**: + - Increase water surface Y if characters are above water + - Adjust AABox size in physics.cpp + - Modify buoyancy/drag coefficients + +## Key Code Changes Made + +1. **BuoyancySystem.cpp/hpp**: + - Added camera position tracking + - Added gravity factor caching for characters + - Added debug logging system + - Fixed broadphase query position + +2. **physics.cpp**: + - Fixed broadphase query to include MOVING layer + - Ensured character bodies are detected + +3. **EditorApp.cpp/hpp**: + - Added `--debug-buoyancy` command line option + - Added `setDebugBuoyancy()` method + - Updated camera position to buoyancy system each frame + +4. **EditorCamera.hpp**: + - Added `getPosition()` method + +5. **main.cpp**: + - Added command line argument parsing for `--debug-buoyancy` + +## Expected Behavior After Fixes + +1. Characters should sink into water (gravity enabled) +2. Buoyancy forces should push characters upward +3. Debug logs should show bodies detected in water +4. Character gravity should be restored when leaving water +5. Water detection area should follow camera movement + +## Troubleshooting + +If characters still aren't affected: + +1. **Check debug logs**: Ensure bodies are being detected +2. **Verify water surface Y**: Characters must be below this value +3. **Check physics layers**: Characters should be in MOVING layer +4. **Test with simple objects**: Create a simple box to verify buoyancy works +5. **Adjust AABox size**: Increase detection area if characters are far from camera + +The system is now properly configured to detect characters in water and apply buoyancy forces with comprehensive debugging capabilities. \ No newline at end of file