ADD: Update Docs

This commit is contained in:
2025-12-17 01:43:13 +09:00
parent 5b62c57d0c
commit fa0298e4c1
9 changed files with 1540 additions and 52 deletions

View File

@@ -7,6 +7,9 @@ For details on the underlying systems, see also:
- `docs/Scene.md` cameras, draw context, instances, picking.
- `docs/EngineContext.md` access to managers and perframe state.
- `docs/RenderGraph.md` rendergraph API for custom passes.
- `docs/InputSystem.md` keyboard, mouse, and cursor mode handling.
- `docs/Picking.md` object selection, hover detection, and drag-box multi-select.
- `docs/ImGuiSystem.md` immediate-mode UI integration and debug widgets.
---
@@ -24,6 +27,7 @@ Implementation: `src/core/game_api.cpp`
- Postprocessing (tonemap, bloom, FXAA).
- Camera control.
- Picking and rendergraph pass toggles.
- Input handling (keyboard, mouse, cursor modes).
Typical creation:
@@ -184,6 +188,152 @@ This writes into `VulkanEngine::_rgPassToggles` and is applied during RenderGrap
---
## Input System
Header: `src/core/input/input_system.h`
Docs: `docs/InputSystem.md`
The engine provides a unified input abstraction layer that wraps SDL2 events. Access it via `VulkanEngine::input()` or store a reference during initialization.
### Polled State (Recommended for Games)
Query current keyboard/mouse state each frame:
```cpp
void Game::update(VulkanEngine& engine)
{
const InputState& input = engine.input().state();
// Movement (held keys)
glm::vec3 move{0.0f};
if (input.key_down(Key::W)) move.z -= 1.0f;
if (input.key_down(Key::S)) move.z += 1.0f;
if (input.key_down(Key::A)) move.x -= 1.0f;
if (input.key_down(Key::D)) move.x += 1.0f;
// Sprint modifier
float speed = input.modifiers().shift ? 10.0f : 5.0f;
player.move(move * speed * dt);
// Fire on left click (just pressed this frame)
if (input.mouse_pressed(MouseButton::Left))
{
player.fire();
}
// Toggle menu on Escape (just pressed)
if (input.key_pressed(Key::Escape))
{
ui.toggle_menu();
}
// Mouse look (right button held)
if (input.mouse_down(MouseButton::Right))
{
engine.input().set_cursor_mode(CursorMode::Relative);
glm::vec2 delta = input.mouse_delta();
camera.rotate(delta.x * 0.1f, delta.y * 0.1f);
}
else
{
engine.input().set_cursor_mode(CursorMode::Normal);
}
// Scroll wheel for zoom
float scroll = input.wheel_delta().y;
if (scroll != 0.0f)
{
camera.zoom(scroll * 0.5f);
}
}
```
### Key State Types
- `key_down(Key)` / `mouse_down(MouseButton)` — true while held (continuous actions)
- `key_pressed(Key)` / `mouse_pressed(MouseButton)` — true only on the frame it was pressed (one-shot)
- `key_released(Key)` / `mouse_released(MouseButton)` — true only on the frame it was released
### Available Keys
Letters: `Key::A` through `Key::Z`
Numbers: `Key::Num0` through `Key::Num9`
Special: `Key::Enter`, `Key::Escape`, `Key::Space`, `Key::Tab`, `Key::Backspace`
Modifiers: `Key::LeftShift`, `Key::LeftCtrl`, `Key::LeftAlt`, `Key::LeftSuper` (and Right variants)
### Mouse Buttons
`MouseButton::Left`, `MouseButton::Middle`, `MouseButton::Right`, `MouseButton::X1`, `MouseButton::X2`
### Cursor Modes
```cpp
enum class CursorMode : uint8_t
{
Normal = 0, // Default visible cursor
Hidden = 1, // Hidden but not captured
Relative = 2, // FPS-style: hidden + captured, only delta matters
};
// Set via:
engine.input().set_cursor_mode(CursorMode::Relative);
```
### Mouse Position and Motion
```cpp
glm::vec2 pos = input.mouse_position(); // Screen coordinates (pixels)
glm::vec2 delta = input.mouse_delta(); // Frame motion delta
glm::vec2 wheel = input.wheel_delta(); // Scroll wheel delta
```
### Modifier Keys
```cpp
InputModifiers mods = input.modifiers();
if (mods.ctrl && input.key_pressed(Key::S))
{
save_game();
}
```
### Event-Driven Access (For UI)
For text input or other event-driven needs:
```cpp
for (const InputEvent& ev : engine.input().events())
{
if (ev.type == InputEvent::Type::KeyDown)
{
if (ev.key == Key::Backspace)
{
text_field.delete_char();
}
}
else if (ev.type == InputEvent::Type::MouseWheel)
{
scroll_view.scroll(ev.wheel_delta.y);
}
}
```
### Window State
```cpp
if (engine.input().quit_requested())
{
// Handle window close
}
if (engine.input().window_minimized())
{
// Skip heavy rendering
}
```
---
## VulkanEngine Helpers
Header: `src/core/engine.h`
@@ -300,66 +450,183 @@ Typical usage:
---
## Picking & Selection (Interaction)
## Picking System
Picking lives in `SceneManager` and is wired into `VulkanEngine`s frame loop.
Header: `src/core/picking/picking_system.h`
Docs: `docs/Picking.md`
Header: `src/scene/vk_scene.h`
Implementation: `src/scene/vk_scene_picking.cpp`
The engine provides a unified picking system that handles click selection, hover detection, and drag-box multi-select. Access it via `VulkanEngine::picking()`.
### SingleObject Ray Picking
### Accessing Pick Results
- `bool pick(const glm::vec2 &mousePosPixels, RenderObject &outObject, glm::vec3 &outWorldPos);`
- Input:
- `mousePosPixels` window coordinates (SDL style), origin at topleft.
- Output on success:
- `outObject` closest `RenderObject` hit by the camera ray.
- `outWorldPos` precise worldspace hit position (uses mesh BVH when available).
- Returns:
- `true` if any object was hit, otherwise `false`.
```cpp
void Game::handle_interaction(VulkanEngine& engine)
{
PickingSystem& picking = engine.picking();
### IDBuffer Picking
// Last click selection
const PickingSystem::PickInfo& pick = picking.last_pick();
if (pick.valid)
{
fmt::println("Selected: {}", pick.ownerName);
interact_with(pick.ownerName, pick.worldPos);
}
- `bool resolveObjectID(uint32_t id, RenderObject &outObject) const;`
- Takes an ID read back from the ID buffer and resolves it to the corresponding `RenderObject` in the latest `DrawContext`.
- Used by the engine when `_useIdBufferPicking` is enabled to implement asynchronous picking.
// Current hover (for tooltips)
const PickingSystem::PickInfo& hover = picking.hover_pick();
if (hover.valid)
{
show_tooltip(hover.ownerName);
}
### Rectangle Selection (Drag Box)
// Drag-box multi-select
for (const auto& sel : picking.drag_selection())
{
if (sel.valid)
{
add_to_selection(sel.ownerName);
}
}
}
```
- `void selectRect(const glm::vec2 &p0, const glm::vec2 &p1, std::vector<RenderObject> &outObjects) const;`
- Inputs:
- `p0`, `p1` opposite corners of a windowspace rectangle (topleft origin).
- Output:
- `outObjects` appended with all `RenderObject`s whose projected bounds intersect the rectangle.
- Internals:
- Uses `sceneData.viewproj` and an NDCspace bounds test to determine overlap.
### PickInfo Structure
### Typical Game Usage
```cpp
struct PickInfo
{
MeshAsset *mesh; // Source mesh
LoadedGLTF *scene; // Source glTF
Node *node; // glTF node
RenderObject::OwnerType ownerType; // StaticGLTF, GLTFInstance, MeshInstance
std::string ownerName; // Logical name (e.g., "player")
WorldVec3 worldPos; // Hit position (double-precision)
glm::mat4 worldTransform; // Object transform
uint32_t indexCount, firstIndex; // Picked surface indices
uint32_t surfaceIndex; // Surface index in mesh
bool valid; // True if hit something
};
```
- Hover tooltips:
- Track mouse position in window coordinates.
- Use `SceneManager::pick` directly, or read `VulkanEngine::get_last_pick()` and/or `_hoverPick` as documented in `Scene.md`.
- Object selection / interaction:
- On mouse click release, inspect `engine->get_last_pick()`:
- If `valid`, dispatch interaction based on `ownerType` / `ownerName` (e.g. select unit, open door).
- Multiselect:
- When implementing drag selection, call `SceneManager::selectRect` with the drag rectangle to get all hits, or reuse the engines `_dragSelection` mechanism.
### Picking Modes
```cpp
// CPU ray picking (default) - immediate, BVH-accelerated
picking.set_use_id_buffer_picking(false);
// ID-buffer picking - pixel-perfect, 1-frame latency
picking.set_use_id_buffer_picking(true);
```
### Owner Types
```cpp
enum class OwnerType
{
None,
StaticGLTF, // Loaded via loadScene()
GLTFInstance, // Runtime glTF instance
MeshInstance, // Runtime mesh instance
};
```
---
## ImGui / ImGuizmo Editor Utilities
## ImGui System
File: `src/core/engine_ui.cpp`
Header: `src/core/ui/imgui_system.h`
Docs: `docs/ImGuiSystem.md`
These are primarily debug/editor features but can be kept in a game build to provide ingame tools.
The engine integrates Dear ImGui for debug UI and editor tools. Access it via `VulkanEngine::imgui()`.
- Main entry:
- `void vk_engine_draw_debug_ui(VulkanEngine *eng);`
- Called once per frame by the engine to build the “Debug” window tabs.
- Useful tools for games:
- Scene tab:
- Spawn glTF instances at runtime using `VulkanEngine::addGLTFInstance(...)`.
- Spawn primitive mesh instances (cube/sphere) using `SceneManager::addMeshInstance(...)`.
- Pointlight editor UI built on `SceneManager` light APIs.
- Object gizmo (ImGuizmo):
- Uses last pick / hover pick as the current target and manipulates transforms via `setMeshInstanceTransform` / `setGLTFInstanceTransform`.
### Adding Custom UI
```cpp
void Game::init(VulkanEngine& engine)
{
// Register your UI callback
engine.imgui().add_draw_callback([this]() {
draw_game_ui();
});
}
void Game::draw_game_ui()
{
if (ImGui::Begin("Game HUD"))
{
ImGui::Text("Score: %d", _score);
ImGui::Text("Health: %.0f%%", _health * 100.0f);
if (ImGui::Button("Pause"))
{
toggle_pause();
}
}
ImGui::End();
}
```
### Input Capture
Always check ImGui input capture before processing game input:
```cpp
void Game::update(VulkanEngine& engine)
{
// Skip game mouse input when ImGui wants it
if (!engine.imgui().want_capture_mouse())
{
handle_mouse_input();
}
// Skip game keyboard input when ImGui wants it
if (!engine.imgui().want_capture_keyboard())
{
handle_keyboard_input();
}
}
```
### Built-in Debug UI
The engine provides comprehensive debug widgets in `src/core/engine_ui.cpp`:
- **Window Tab**: Monitor selection, fullscreen modes, HiDPI info
- **Stats Tab**: Frame time, FPS, draw calls, triangle count
- **Scene Tab**: Instance spawning, point light editor, ImGuizmo gizmos
- **Render Graph Tab**: Pass toggles, resource tracking
- **Texture Streaming Tab**: VRAM budget, cache stats
- **Shadows Tab**: Shadow mode, cascade visualization
- **Post Processing Tab**: Tonemapping, bloom, FXAA, SSR settings
### ImGuizmo Integration
For 3D transform gizmos on selected objects:
```cpp
#include "ImGuizmo.h"
void draw_gizmo(const PickingSystem::PickInfo& pick,
const glm::mat4& view, const glm::mat4& proj)
{
if (!pick.valid) return;
glm::mat4 transform = pick.worldTransform;
ImGuizmo::SetOrthographic(false);
ImGuizmo::SetDrawlist();
ImGuiIO& io = ImGui::GetIO();
ImGuizmo::SetRect(0, 0, io.DisplaySize.x, io.DisplaySize.y);
if (ImGuizmo::Manipulate(glm::value_ptr(view),
glm::value_ptr(proj),
ImGuizmo::TRANSLATE,
ImGuizmo::WORLD,
glm::value_ptr(transform)))
{
// Apply transform to the picked object
scene->setGLTFInstanceTransform(pick.ownerName, transform);
}
}
```