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:
@@ -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.
|
||||
Reference in New Issue
Block a user