some docs
This commit is contained in:
@@ -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`)
|
||||
@@ -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.
|
||||
Reference in New Issue
Block a user