some docs

This commit is contained in:
2026-05-25 04:19:03 +03:00
parent b71b599d9c
commit 1a0fb87b93
2 changed files with 389 additions and 0 deletions
+217
View File
@@ -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<CharacterComponent, TransformComponent>().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`)
+172
View File
@@ -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.