Skip to content
Closed
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -414,3 +414,4 @@ FodyWeavers.xsd

# JetBrains CLion
.idea
imgui.ini
14 changes: 8 additions & 6 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,6 @@ cmake --build build

# Run the main example
./build/examples/sample-scenes/WeirdSamples

# muOS cross-compile (aarch64, uses podman)
./scripts/anbernic/build-muos.sh
./scripts/anbernic/deploy-muos.sh # build + deploy via MTP
./scripts/anbernic/deploy-muos.sh --no-build # deploy only
./scripts/anbernic/fetch-logs.sh # pull log.txt + screenshots
```

There are no tests. CI runs `ctest` but no test targets are defined.
Expand All @@ -27,6 +21,7 @@ There are no tests. CI runs `ctest` but no test targets are defined.
| `WEIRD_DISABLE_IMGUI` | `OFF` | Strip ImGui (used for muOS build) |
| `WEIRD_TEST_HOOKS` | `OFF` | Enables `WEIRD_AUTO_QUIT_SECONDS` / `WEIRD_SCREENSHOT_FRAME` env vars |
| `WEIRD_ENGINE_ENABLE_ASAN` | `OFF` | AddressSanitizer |
| `WEIRD_ENGINE_ENABLE_ASSERTS` | Debug/RelWithDebInfo | Enables `WEIRD_ASSERT` runtime assertions (abort on violation); disabled in Release |
| `WEIRD_USE_FBDEV_EGL` | `OFF` | fbdev EGL backend for Mali devices (no GBM/KMS) |
| `WEIRD_ENGINE_USE_RUNTIME_ASSETS` | `OFF` | Load shaders/fonts from `./shaders/` `./fonts/` instead of source tree |

Expand All @@ -41,6 +36,7 @@ There are no tests. CI runs `ctest` but no test targets are defined.
- `sample-scenes` → `WeirdSamples` (main demo)
- `3d-experiments`, `opengl-experiments` — other demos
- `empty-project` — starter template
- **ServiceProvider pattern**: `Scene` state is highly encapsulated. Game systems should use `ServiceProvider` (passed into update/render loops) to interact with rendering, audio, or physics systems instead of accessing `Scene` internals.
- Entry point for games: `WeirdEngine::start(sceneManager, ...)` in `include/weird-engine.h`.

## Dependencies
Expand All @@ -59,3 +55,9 @@ There are no tests. CI runs `ctest` but no test targets are defined.
- The `build/` and `build-muos/` directories are separate CMake trees; do not mix them.
- `compile_flags.txt` exists for clangd; it does not drive the actual build.
- The `.vscode/settings.json` enables `WEIRD_ENGINE_BUILD_EXAMPLES=ON` by default.

## Commit Guidelines

- **Naming Convention**: Prefix all commit messages with the affected module or system name, followed by a colon and a space. Keep the prefix lowercase.
- Prefix Examples: `scene:`, `core:`, `physics:`, `renderer:`, `examples:`, `tools:`, `core/assert:`
- Full Example: `physics: add BodyUserData for attaching custom data to rigidbodies`
15 changes: 15 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,20 @@ if(WEIRD_TEST_HOOKS)
add_compile_definitions(WEIRD_TEST_HOOKS)
endif()

# Runtime assertions: enabled by default in debug-like configurations
# (Debug, RelWithDebInfo), disabled in Release/MinSizeRel. Games that build
# the engine via add_subdirectory inherit this through the PUBLIC definition.
set(WEIRD_ENGINE_ENABLE_ASSERTS_DEFAULT OFF)
if(CMAKE_BUILD_TYPE MATCHES "^(Debug|RelWithDebInfo)$"
OR CMAKE_CONFIGURATION_TYPES MATCHES "(^|;)Debug(;|$)"
OR CMAKE_CONFIGURATION_TYPES MATCHES "(^|;)RelWithDebInfo(;|$)")
set(WEIRD_ENGINE_ENABLE_ASSERTS_DEFAULT ON)
endif()
option(WEIRD_ENGINE_ENABLE_ASSERTS "Enable runtime assertions (WEIRD_ASSERT)" ${WEIRD_ENGINE_ENABLE_ASSERTS_DEFAULT})
if(WEIRD_ENGINE_ENABLE_ASSERTS)
target_compile_definitions(${PROJECT_NAME} PUBLIC WEIRD_ENABLE_ASSERTS=1)
endif()

if(NOT WEIRD_DISABLE_IMGUI)
# ImGui setup
set(IMGUI_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third-party/imgui)
Expand Down Expand Up @@ -222,6 +236,7 @@ if(WEIRD_ENGINE_BUILD_EXAMPLES)
add_subdirectory(examples/3d-experiments)
add_subdirectory(examples/opengl-experiments)
add_subdirectory(examples/sample-scenes)
add_subdirectory(examples/empty-project)
endif()

# Tools
Expand Down
46 changes: 28 additions & 18 deletions examples/3d-experiments/include/Classic.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ class ClassicScene : public Scene3D
Entity m_ball;

// Inherited via Scene
void onStart(ECSManager& ecs) override
void onStart(ECSManager& ecs, ServiceProvider& services) override
{
m_debugFly = true;
services.debug().setDebugFly(true);

auto& redMat = createMaterial();
auto& redMat = services.materials().createMaterial();
redMat.color = vec4(.8f, 0.2f, 0.2f, 1.0f);

auto& orangeMat = createMaterial();
auto& orangeMat = services.materials().createMaterial();
orangeMat.color = vec4(.95f, 0.4f, 0.1f, 1.0f);

auto& floorMaterial = createMaterial();
auto& floorMaterial = services.materials().createMaterial();
floorMaterial.color = vec4(1.0f, 1.0f, 1.0f, 1.0f);
floorMaterial.secondaryColor = vec4(0.4f, 0.4f, 0.6f, 1.0f);
floorMaterial.metallic = 0.7f;
Expand All @@ -36,7 +36,7 @@ class ClassicScene : public Scene3D

MeshRenderer& mr = ecs.addComponent<MeshRenderer>(entity);

auto id = m_resourceManager.getMeshId(ASSETS_PATH "monkey/demo.gltf", entity, true);
auto id = services.resources().getMeshId("monkey/demo.gltf", entity, true);
mr.mesh = id;
// mr.materialIndex = floorMaterial.id;

Expand All @@ -56,28 +56,38 @@ class ClassicScene : public Scene3D

{
float vars1[8] = {25.0f, 10.0f, 5.0f, 0.5f, 13.0f, 0.0f}; // Custom shape
Entity start = addShape(DefaultShapes::STAR, vars1, orangeMat, CombinationType::Addition, true, 0);
Entity start =
services.shapes().addShape(DefaultShapes::STAR, vars1, orangeMat, CombinationType::Addition, true, 0);
}

{
float vars1[8] = {}; // Custom shape
Entity start = addShape(DefaultShapes3D::PLANE, vars1, floorMaterial, CombinationType::Addition, false);
Entity start = services.shapes().addShape(DefaultShapes3D::PLANE, vars1, floorMaterial,
CombinationType::Addition, false);
}

getLigths().push_back(Light{0, glm::vec3(0.0f, 3.0f, 0.0f), 0, glm::vec3(0.35f, 0.45f, 0.5f),
glm::vec4(1.0f, 0.95f, 0.9f, 2.0f)});
{
Entity entity = ecs.createEntity();
Transform& t = ecs.addComponent<Transform>(entity);
t.position = glm::vec3(0.0f, 3.0f, 0.0f);
t.rotation = glm::vec3(0.35f, 0.45f, 0.5f);

LightComponent& lc = ecs.addComponent<LightComponent>(entity);
lc.type = LightType::Directional;
lc.color = glm::vec4(1.0f, 0.95f, 0.9f, 2.0f);
}

ecs.getComponent<Transform>(m_mainCamera).position = vec3(0, 2, 10);
ecs.getComponent<Transform>(services.render().getCameraEntity()).position = vec3(0, 2, 10);
}

void onUpdate(float delta, ECSManager& ecs) override
void onUpdate(ECSManager& ecs, ServiceProvider& services) override
{
if (Input::GetKeyDown(Input::Q))
if (services.input().getKeyDown(Input::Q))
{
setSceneComplete();
services.sceneControl().goToNextScene();
}

Transform& cameraTransform = ecs.getComponent<Transform>(m_mainCamera);
Transform& cameraTransform = ecs.getComponent<Transform>(services.render().getCameraEntity());

return;

Expand All @@ -87,9 +97,9 @@ class ClassicScene : public Scene3D

{
Transform& t = ecs.getComponent<Transform>(m_ball);
// t.position.z = 10 * sinf(getTime());
t.position.x = 2.0f * sinf(-getTime());
t.position.z = 2.0f * cosf(-getTime());
// t.position.z = 10 * sinf(services.time().time());
t.position.x = 2.0f * sinf(-services.time().time());
t.position.z = 2.0f * cosf(-services.time().time());
}

// t.position = cameraTransform.position + vec3(-10, -6, -20);
Expand Down
78 changes: 46 additions & 32 deletions examples/3d-experiments/include/CornellBox.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,26 @@ class CornellBox : public Scene3D
CornellBox() {};

private:
Entity m_sunLight;
// Inherited via Scene
void onStart(ECSManager& ecs) override
void onStart(ECSManager& ecs, ServiceProvider& services) override
{
m_debugFly = true;
services.debug().setDebugFly(true);

auto& ballMat = createMaterial();
auto& ballMat = services.materials().createMaterial();
ballMat.color = vec4(1.0f);
ballMat.metallic = 1.0f;
ballMat.roughness = 0.005f;

auto& redMat = createMaterial();
auto& redMat = services.materials().createMaterial();
redMat.color = vec4(.8f, 0.2f, 0.2f, 1.0f);

auto& greenMat = createMaterial();
auto& greenMat = services.materials().createMaterial();
greenMat.color = vec4(0.1f, .95f, 0.1f, 1.0f);
greenMat.metallic = 0.5f;
greenMat.roughness = 0.1f;

auto& whiteMat = createMaterial();
auto& whiteMat = services.materials().createMaterial();
whiteMat.color = vec4(1.0f, 1.0f, 1.0f, 1.0f);

{
Expand All @@ -55,81 +56,94 @@ class CornellBox : public Scene3D

{
std::shared_ptr<IMathExpression> box = std::make_shared<Primitives3D::Box>();
auto boxId = registerSDF(box);
auto boxId = services.shapes().registerSDF(box);

// Left
{
float vars1[8] = {-2.0f * 2.6f, 2.6f, 0.0f, 2.6f, 2.6f, 2.6f}; // Custom shape
Entity start = addShape(boxId, vars1, redMat, CombinationType::Addition, false);
Entity start = services.shapes().addShape(boxId, vars1, redMat, CombinationType::Addition, false);
}

// Right
{
float vars1[8] = {2.0f * 2.6f, 2.6f, 0.0f, 2.6f, 2.6f, 2.6f}; // Custom shape
Entity start = addShape(boxId, vars1, greenMat, CombinationType::Addition, false);
Entity start = services.shapes().addShape(boxId, vars1, greenMat, CombinationType::Addition, false);
}

// Back
{
float vars1[8] = {0.0f, 2.6f, -2.0f * 2.6f, 3.0f * 2.6f, 2.6f, 2.6f}; // Custom shape
Entity start = addShape(boxId, vars1, whiteMat, CombinationType::Addition, false);
Entity start = services.shapes().addShape(boxId, vars1, whiteMat, CombinationType::Addition, false);
}

// Top
{
float vars1[8] = {0.0f, 3.0f * 2.6f, -2.6f, 3.0f * 2.6f, 2.6f, 2.0f * 2.6f}; // Custom shape
Entity start = addShape(boxId, vars1, whiteMat, CombinationType::Addition, false);
Entity start = services.shapes().addShape(boxId, vars1, whiteMat, CombinationType::Addition, false);
}

// Light hole
{
float vars1[8] = {0.0f, 2.0f * 2.6f, 0.0f, 0.5f, 1.0f, 0.5f}; // Custom shape
Entity start = addShape(boxId, vars1, whiteMat, CombinationType::Subtraction, false);
Entity start = services.shapes().addShape(boxId, vars1, whiteMat, CombinationType::Subtraction, false);
}

// Floor
{
float vars1[8] = {0.0f, -1.0f * 2.6f, -2.6f, 3.0f * 2.6f, 2.6f, 2.0f * 2.6f}; // Custom shape
Entity start = addShape(boxId, vars1, whiteMat, CombinationType::Addition, false);
Entity start = services.shapes().addShape(boxId, vars1, whiteMat, CombinationType::Addition, false);
}

// {
// float vars1[8] = {0.0f, 2.6f, 0.0f, 2.7f, 2.7f, 2.7f}; // Custom shape
// Entity start = addShape(boxId, vars1, DisplaySettings::White, CombinationType::Intersection, false);
// Entity start = services.shapes().addShape(boxId, vars1, DisplaySettings::White,
// CombinationType::Intersection, false);
// }
}

// Sun
getLigths().push_back(Light{0, glm::vec3(0.0f, 0.0f, 0.0f), 0, normalize(glm::vec3(0.0f, 0.0f, 0.0f)),
glm::vec4(1.0f, 1.0f, 1.0f, 0.0f)});
{
m_sunLight = ecs.createEntity();
Transform& t = ecs.addComponent<Transform>(m_sunLight);
t.position = glm::vec3(0.0f, 0.0f, 0.0f);
t.rotation = normalize(glm::vec3(0.0f, 0.0f, 0.0f));

LightComponent& lc = ecs.addComponent<LightComponent>(m_sunLight);
lc.type = LightType::Directional;
lc.color = glm::vec4(1.0f, 1.0f, 1.0f, 0.0f);
}

{
Entity entity = ecs.createEntity();
Transform& t = ecs.addComponent<Transform>(entity);
t.position = glm::vec3(0.0f, (2.0f * 2.6f) + 0.25f, 0.0f);
t.rotation = glm::vec3(0.0f, 0.0f, 0.0f);

getLigths().push_back(Light{1, glm::vec3(0.0f, (2.0f * 2.6f) + 0.25f, 0.0f), 0, glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec4(1.0f, 1.0f, 1.0f, 3.0f)});
LightComponent& lc = ecs.addComponent<LightComponent>(entity);
lc.type = LightType::Point;
lc.color = glm::vec4(1.0f, 1.0f, 1.0f, 3.0f);
}

// getLigths().push_back(
// getLights().push_back(
// Light{1, glm::vec3(0.0f, 0.0f, 0.0f), 0, glm::vec3(0.35f, 0.45f, 0.5f), glm::vec4(0.0f, 1.0f, 0.0f, 1.0f)});

// getLigths().push_back(
// getLights().push_back(
// Light{2, glm::vec3(0.0f, 0.0f, 0.0f), 0, glm::vec3(0.0f, 1.0f, 0.0f), glm::vec4(0.0f, 0.0f, 2.0f, 10.0f)});

ecs.getComponent<Transform>(m_mainCamera).position = vec3(0, 2.6f, 12.0f);
ecs.getComponent<Transform>(services.render().getCameraEntity()).position = vec3(0, 2.6f, 12.0f);
}

void onUpdate(float delta, ECSManager& ecs) override
void onUpdate(ECSManager& ecs, ServiceProvider& services) override
{
if (Input::GetKeyDown(Input::Q))
if (services.input().getKeyDown(Input::Q))
{
setSceneComplete();
services.sceneControl().goToNextScene();
}

auto& cameraTransform = ecs.getComponent<Transform>(m_mainCamera);

// getLigths()[0].position.x = cameraTransform.position.x;
// getLigths()[0].position.y = cameraTransform.position.y;
// getLigths()[0].position.z = cameraTransform.position.z;
auto& cameraTransform = ecs.getComponent<Transform>(services.render().getCameraEntity());

// getLigths()[0].rotation.x = -cameraTransform.rotation.x;
// getLigths()[0].rotation.y = -cameraTransform.rotation.y;
// getLigths()[0].rotation.z = -cameraTransform.rotation.z;
auto& lightTransform = ecs.getComponent<Transform>(m_sunLight);
lightTransform.position = cameraTransform.position;
lightTransform.rotation = -cameraTransform.rotation;
}
};
Loading
Loading