Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,22 @@ target_link_libraries(render_renderer PUBLIC render::core render::platform rende
render_apply_project_options(render_renderer)
render_apply_warnings(render_renderer)


add_library(render_scene STATIC
engine/scene/scene.hpp
engine/scene/scene.cpp
)
add_library(render::scene ALIAS render_scene)
target_include_directories(render_scene PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
target_link_libraries(render_scene PUBLIC render::core render::renderer)
render_apply_project_options(render_scene)
render_apply_warnings(render_scene)

add_library(render_engine STATIC
engine/engine.cpp
)
add_library(render::engine ALIAS render_engine)
target_link_libraries(render_engine PUBLIC render::core render::filesystem render::platform render::renderer render::serialization)
target_link_libraries(render_engine PUBLIC render::core render::filesystem render::platform render::renderer render::serialization render::scene)
render_apply_project_options(render_engine)
render_apply_warnings(render_engine)

Expand Down Expand Up @@ -193,6 +204,11 @@ if(RENDER_BUILD_TESTS)
render_apply_project_options(render_shader_pipeline_tests)
render_apply_warnings(render_shader_pipeline_tests)

add_executable(render_scene_tests tests/scene/scene_tests.cpp)
target_link_libraries(render_scene_tests PRIVATE render::scene)
render_apply_project_options(render_scene_tests)
render_apply_warnings(render_scene_tests)

add_test(NAME unit.platform.types COMMAND render_platform_types_tests)
set_tests_properties(unit.platform.types PROPERTIES LABELS "unit;platform")
add_test(NAME unit.core.runtime COMMAND render_core_runtime_tests)
Expand All @@ -205,12 +221,14 @@ if(RENDER_BUILD_TESTS)
set_tests_properties(unit.renderer.lifecycle PROPERTIES LABELS "unit;renderer")
add_test(NAME unit.renderer.shader_pipeline COMMAND render_shader_pipeline_tests)
set_tests_properties(unit.renderer.shader_pipeline PROPERTIES LABELS "unit;renderer;shader")
add_test(NAME unit.scene.runtime COMMAND render_scene_tests)
set_tests_properties(unit.scene.runtime PROPERTIES LABELS "unit;scene")
add_test(NAME headless.smoke.startup COMMAND render_headless_validation)
set_tests_properties(headless.smoke.startup PROPERTIES LABELS "headless;smoke")

add_custom_target(render_test_unit
COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure --label-regex unit
DEPENDS render_platform_types_tests render_core_runtime_tests render_serialization_tests render_filesystem_tests render_renderer_lifecycle_tests render_shader_pipeline_tests
DEPENDS render_platform_types_tests render_core_runtime_tests render_serialization_tests render_filesystem_tests render_renderer_lifecycle_tests render_shader_pipeline_tests render_scene_tests
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
COMMENT "Running render unit tests"
)
Expand Down
8 changes: 7 additions & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Architecture Snapshot (Statement 5)
# Architecture Snapshot (Statements 5-11)

## Runtime layering now implemented

Expand Down Expand Up @@ -34,3 +34,9 @@
5. **Core runtime layer (`engine/core`)**
- Foundational math, transforms, camera helpers, colors, UUID/hash/random utilities.
- Shared runtime services for memory, threading, logging, assertions, and profiling hooks.


6. **Scene runtime layer (`engine/scene`)**
- Engine-owned scene graph with stable node handles, transform hierarchy, visibility, and debug names.
- Optional camera/light/renderable attachments with traversal and renderer extraction helpers.
- Explicit update step for dirty world transform propagation (`Scene::update_world_transforms`).
12 changes: 12 additions & 0 deletions docs/rendering.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,15 @@ Deferred to later statements:
- compute shader runtime integration (manifest structure already reserves this)
- centralized material system on top of `ShaderProgramId`
- full editor/content pipeline tooling around variants and dependency graphs


## Scene integration (Statement 11)

`render_shell` now drives rendering through `engine/scene`:

- scene nodes carry camera/light/renderable attachments
- frame flow calls `Scene::update_world_transforms()` before extraction
- view matrices come from `Scene::build_camera_view(...)`
- draw submissions are emitted from `Scene::collect_visible_renderables(...)`

This establishes a stable engine-owned scene/runtime boundary above the renderer API.
106 changes: 106 additions & 0 deletions docs/scene.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# Scene System (Statement 11)

## Module layout

- `engine/scene/scene.hpp`: public scene API and component data.
- `engine/scene/scene.cpp`: handle validation, hierarchy, dirty propagation, traversal, extraction.
- `engine/scene/README.md`: focused module notes.

The scene module is engine-owned and only references engine-owned core/render interfaces.

## Identity model

Each node uses `SceneNodeId { index, generation }`:

- `index` addresses storage slot
- `generation` invalidates stale handles after destroy/reuse

Destroyed nodes increment generation and return slot to a free-list. This prevents stale handles from silently targeting unrelated nodes.

## Transform + hierarchy rules

Each node stores:

- local transform (`core::Transform`)
- cached world transform (`core::Transform`)
- parent and children links

`Scene::update_world_transforms()` performs explicit top-down propagation from roots.

- Dirty state is pushed to descendants on local transform or hierarchy changes.
- Recompute is skipped for nodes that are not dirty and do not have dirty ancestry.

Reparenting policies:

- keep local: retain local transform values
- keep world: solve new local transform from current world and target parent world

Cycles are rejected with ancestor walk checks.

## Camera/light/renderable representation

### Cameras

`CameraComponent` supports:

- perspective + orthographic params (via `core::camera` types)
- enabled flag
- layer mask for filtering compatibility

`build_camera_view(aspect_ratio)` resolves active/fallback camera and returns derived view/projection matrices.

### Lights

`LightComponent` supports:

- directional / point types
- color, intensity, range
- enabled flag

Light direction/position come from node world transform.

### Renderables

`RenderableComponent` supports:

- mesh handle references
- program handle references
- draw state
- enabled flag + layer mask

Scene APIs keep renderer backend details hidden (no raw bgfx exposure).

## Visibility + debug names

Nodes expose:

- `NodeVisibility { enabled, layer_mask }`
- debug names as human-readable labels

Duplicate names are allowed. `find_nodes_by_name` returns all matches for tooling use.

## Renderer integration at this stage

`render_shell` now builds and renders through the scene:

- creates root/camera/light/renderable nodes
- parents nodes into hierarchy
- updates scene transforms each frame
- derives camera view/projection from scene
- collects visible renderables and submits to renderer

This validates the scene as the canonical runtime spatial layer.

## Current scope vs deferred

Implemented now:

- core node runtime, hierarchy, transforms, cameras/lights/renderables
- traversal/query/extraction helpers
- unit tests for handle, hierarchy, transform, components, visibility, naming

Deferred:

- binary/text scene serialization schema and IO flow
- culling structures and batching
- richer editor/runtime inspection APIs
46 changes: 46 additions & 0 deletions engine/scene/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Scene Runtime (Statement 11)

`engine/scene` provides the engine-owned spatial scene foundation.

## Current capabilities

- Stable scene node handles with generation checks (`SceneNodeId`).
- Parent-child hierarchy with cycle prevention and explicit reparent policy.
- Local + world transforms using `core::Transform` and explicit `update_world_transforms()`.
- Optional node attachments for camera, light, and renderable data.
- Node visibility + layer masks and renderable-specific layer masks.
- Debug names and duplicate-name lookup.
- Scene traversal and renderer-facing extraction helpers (`build_camera_view`, `collect_visible_renderables`, `collect_visible_lights`).

## Update model

The scene does not mutate world transforms implicitly for every operation. Call `Scene::update_world_transforms()` after structural/transform edits and before extraction/submission.

Dirty propagation rules:

- writing local transform marks node subtree dirty
- reparent/unparent marks affected subtree dirty
- update pass recomputes world transforms top-down from roots

## Reparent policy

`set_parent` and `clear_parent` take `ReparentPolicy`:

- `KeepLocalTransform`: preserve local transform fields, world changes relative to new parent
- `KeepWorldTransform`: preserve world transform and recompute local relative to new parent

## Visibility rules

A node contributes renderables/lights only when:

- node visibility `enabled == true`
- component `enabled == true`
- node and component layer masks overlap caller-provided layer mask

## Deferred for later statements

- scene serialization format + load/save pipelines
- culling acceleration structures
- advanced camera controllers and camera blending
- shadow map authoring and broader light model
- material graph / resource binding systems
Loading
Loading