Import Oxide engine (Stages 0–10) under MIT license

Full project snapshot migrated to new Gitea remote without history:
engine, editor, physics, script, examples, tests, docs, and assets.
Relicensed from GPLv3 to MIT and updated repo URLs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Homer Simpson
2026-07-05 20:41:02 +02:00
parent 2afb56b329
commit 9eead719b0
157 changed files with 47270 additions and 2 deletions
+90
View File
@@ -0,0 +1,90 @@
# Conventions
Cross-cutting conventions every Oxide system follows. These are decided once,
here, so individual systems don't each invent their own.
## Coordinate system
Oxide uses a **right-handed** coordinate system, consistent with `glam`'s
`*_rh` matrix constructors and the glTF asset format the engine will load.
In a default (identity) orientation:
| Axis | Direction | Local accessor on `Transform` |
|------|-----------|-------------------------------|
| `+X` | right | `Transform::right()` |
| `+Y` | up | `Transform::up()` |
| `-Z` | forward (the direction a camera/object looks) | `Transform::forward()` |
So **forward is `-Z`**. This matches the convention used by glTF, OpenGL, and
`glam`'s view-matrix helpers, which keeps asset import and camera math
consistent.
`Transform::looking_at(eye, target, up)` produces an orientation whose
`forward()` points from `eye` toward `target`.
## Rotations
- Rotations are stored as **unit quaternions** (`glam::Quat`), not Euler angles
or matrices, to avoid gimbal lock and accumulate cleanly under composition.
- Euler-angle helpers (`Quat::from_euler`) are available for authoring, but the
canonical stored form is always a quaternion.
- Angles are in **radians**. Convert from degrees explicitly at the boundary
(`90_f32.to_radians()`).
## Transform composition
- Transforms compose **parent-first**: `parent.mul_transform(&child)` yields the
child resolved in the parent's space, matching `parent_matrix * child_matrix`.
- The effective matrix order is `T * R * S` — scale is applied first, then
rotation, then translation.
- Composition is **exact** for uniform scale. With non-uniform scale plus
rotation the true product is not representable as a single translation /
rotation / scale triple, so the result is the closest TRS approximation
(re-decomposed from the matrix). Prefer uniform scale in deep hierarchies.
See [math.md](math.md#transform) for details.
## Units
- **Length:** meters. Physics (`rapier3d`, Stage 6) tunes its solver for
meter-scale geometry, so the whole engine adopts meters to avoid conversions.
- **Time:** seconds (`f32` for per-frame deltas; a fixed timestep drives physics
from Stage 6).
- **Angles:** radians (see above).
- **Mass:** kilograms (Stage 6+).
## Numeric type
- The engine is **`f32`-first**. `glam`'s `f32` types are the default throughout;
`f64` is used only where a specific algorithm demands it.
- Comparisons use explicit epsilons rather than `==` on floats. Helpers and tests
use a small tolerance (commonly `1e-4``1e-6`) appropriate to the operation.
## Color and color space
- `Color` stores **linear** RGBA as `f32`. Lighting and blending math is correct
only in linear space, so that is the engine's working space.
- Values are nominally in `[0, 1]` but are **not clamped** — values above `1.0`
represent HDR / emissive intensity.
- Conversions to and from 8-bit **sRGB** (the space of color pickers, image
files, and `#RRGGBB` hex) are explicit: `Color::from_srgb_u8`,
`Color::from_hex`, `Color::to_srgb_u8`. Never treat raw 8-bit values as linear.
## Geometry primitives
- An [`Aabb`](math.md#aabb) is *empty* when any `min` component exceeds the
corresponding `max`; `Aabb::EMPTY` is the identity for `union`.
- A [`Ray`](math.md#ray) always stores a **normalized** direction, so its
parameter `t` is a true distance.
- A [`Plane`](math.md#plane) is stored in **Hessian normal form** (`normal·p + d
= 0`) with a unit normal; the positive half-space is the side the normal points
toward.
- A [`Frustum`](math.md#frustum) stores six planes with **inward-facing**
normals; a point is inside when it is in the positive half-space of all six.
## Determinism
Procedural systems (Stage 11+) must be **deterministic**: the same seed always
produces the same output. Tests that need randomness use a small, explicit,
seeded PRNG rather than a system RNG, so failures are reproducible.