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`)