# Architecture

This document explains how Oxide is structured and the principles that govern how
it is built. For per-system detail, see the topic documents (e.g. [math.md](math.md)).

## Goals

Oxide is a general-purpose 3D game engine written in Rust, built to make **any**
3D game — scaling from stylized low-poly to realistic graphics — and to **ship
only what each game uses**. It is built in two phases: a **general-purpose engine**
(Phase 1, scene graph, render pass pipeline, input, UI, physics, scripting,
animation, particles, shaders, audio, content kit, and game export) and a set of
optional, feature-gated **built-in modules** (Phase 2: ray-traced sound, developer
console, procedural toolkit, terrain, open world, pathfinding/AI, water). The
guiding idea is **build tools, not games**, all driven through a first-class
**in-engine editor**. See [`PLAN.md`](../PLAN.md) for the staged roadmap.

## Design philosophy

These principles are non-negotiable and shape every decision:

1. **Build in stages.** Each stage produces a usable, standalone artifact and
   must be fully tested and stable before the next begins. See
   [development.md](development.md) and [`PLAN.md`](../PLAN.md).
2. **Composability.** Every system should be usable independently of the others.
   You should be able to pull in the math module, or the scene graph, without
   dragging in the renderer.
3. **Correctness and clarity over premature optimization.** Optimize when a
   benchmark says to, not before.
4. **Minimal public surface.** Internal complexity is fine; the external API
   should be small and clean. Modules expose a curated set of types through
   `pub use`, not their whole internal structure.
5. **No feature creep between stages.** New ideas go to the backlog, not into the
   current stage.
6. **The editor grows with the engine.** `oxide-editor` is a first-class
   deliverable, gaining panels and tools as each stage adds systems.
7. **Build tools, not games.** Ship composable building blocks; genre-specific
   behavior belongs in game code or optional modules.
8. **Ship only what's used.** Subsystems are feature-gated **modules** (from
   Stage 5); an exported game compiles in only the modules it registers.
9. **Scalable fidelity.** A data-driven render pass pipeline lets a project run
   anything from a flat low-poly/stylized look to a full realistic stack, paying
   only for the passes it enables.
10. **Modules are the primary extension point.** A module registers engine logic
    *and* editor UI *and* its own settings through one documented API; anyone —
    including AI agents — can write one.

## Workspace layout

Oxide is a single Cargo workspace. Crates share version, edition, license, and
dependency versions through `[workspace.package]` and `[workspace.dependencies]`
in the root `Cargo.toml`.

```
Oxide/
├── engine/      # oxide-engine  — the core library (all engine systems)
├── editor/      # oxide-editor  — the in-engine editor binary
├── examples/    # oxide-examples — runnable examples, one+ per stage
├── tests/       # oxide-tests   — integration / end-to-end test harness
├── docs/        # this documentation
├── assets/      # logos and shared assets
├── install.sh   # release build + system install
├── PLAN.md      # authoritative staged roadmap
├── README.md    # short project overview
└── CLAUDE.md    # rules and context for AI-assisted development
```

### Crate responsibilities

- **`oxide-engine`** — the library that contains every engine system. It is
  organized as one module per system (`math`, and later `scene`, `render`,
  `physics`, …). Each module is independently usable and re-exports its public
  types. A `prelude` module collects the most common imports.
- **`oxide-editor`** — the binary users run. It depends on `oxide-engine` and
  builds a UI on top of engine systems (its own window with a placeholder
  viewport since Stage 2; egui panels from Stage 3). It never contains engine
  logic itself; it is a consumer of the engine.
- **`oxide-examples`** — small, focused programs that each demonstrate one
  stage's capabilities. They double as manual-review artifacts and as living
  documentation. `publish = false`; they are never installed.
- **`oxide-tests`** — integration tests that exercise the engine the way a real
  consumer would, including cross-module scenarios and fuzz/property tests.

## Engine module structure

Inside `oxide-engine`, each system is a module under `engine/src/`. The pattern,
established by the math module, is:

```
engine/src/
├── lib.rs              # declares modules, defines the prelude
├── math/
│   ├── mod.rs          # module docs + curated `pub use` re-exports
│   ├── transform.rs    # one type/concept per file, with its own tests
│   ├── aabb.rs
│   └── ...
├── render/             # Stage 2: GPU acquisition + surface clear loop
│   ├── mod.rs          # RenderError, clear_view, re-exports
│   ├── gpu.rs          # Gpu (instance/adapter/device/queue)
│   └── context.rs      # RenderContext (surface, resize, render_frame)
└── window/             # Stage 2: window + event loop + App trait
    ├── mod.rs          # WindowConfig, `event` re-export module
    ├── app.rs          # App trait, AppCtx
    └── runner.rs       # winit ApplicationHandler internals
```

Rules of thumb:

- **One concept per file.** Prefer many small focused files over a few large
  ones.
- **Tests live with the code.** Each file has a `#[cfg(test)] mod tests` block
  covering core behavior and edge cases.
- **The module root curates the API.** `mod.rs` decides what is public via
  `pub use`; submodules are private (`mod foo;`, not `pub mod foo;`) unless there
  is a reason to expose the path.
- **The prelude is the front door.** `oxide_engine::prelude::*` brings in the
  types a typical consumer needs, including re-exported third-party math types so
  downstream code needs only one dependency for everyday work.

## Key dependencies

Chosen for portability and a lightweight footprint:

| Concern | Crate | Notes |
|---------|-------|-------|
| Math | [`glam`](https://docs.rs/glam) | SIMD-friendly vectors/quats/matrices; `serde` feature enabled |
| Graphics | [`wgpu`](https://docs.rs/wgpu) | Portable across Vulkan/Metal/DX12 (since Stage 2; re-exported as `oxide_engine::wgpu`) |
| Windowing | [`winit`](https://docs.rs/winit) | Cross-platform windows and events (since Stage 2; re-exported as `oxide_engine::winit`) |
| ECS | [`hecs`](https://docs.rs/hecs) | Lightweight archetypal ECS (Stage 3+) |
| Physics | [`rapier3d`](https://docs.rs/rapier3d) | Rigid bodies and collision (Stage 6+) |
| Editor UI | [`egui`](https://docs.rs/egui) | Immediate-mode UI (Stage 3+) |
| Logging | `log` + `env_logger` | Facade + env-driven backend |
| Errors | `anyhow` + `thiserror` | Application vs. library error handling |
| Serialization | `serde` + `ron` | Scene/asset (de)serialization (Stage 3+) |

## Error handling and logging

- **Libraries (`oxide-engine`)** define their own error types with `thiserror`
  so callers can match on failure modes.
- **Binaries (`oxide-editor`, examples)** use `anyhow` for ergonomic error
  propagation at the top level.
- **Logging** uses the `log` facade throughout the engine; binaries initialize a
  backend (`env_logger`). Control verbosity with `RUST_LOG`, e.g.
  `RUST_LOG=oxide_engine=debug cargo run -p oxide-examples --bin math_demo`.

## Installability

Oxide must remain installable as a Linux package at all times. `install.sh`
builds in release mode and installs the `oxide-editor` binary and assets under a
prefix (`/usr/local` by default, overridable with `PREFIX`). Any new installed
binary or asset must be reflected in `install.sh` in the same change.

## See also

- [conventions.md](conventions.md) — coordinate system, units, color space
- [development.md](development.md) — workflow, testing, and how stages progress
- [`PLAN.md`](../PLAN.md) — the full staged roadmap
