roxlap_core/lib.rs
1//! roxlap engine core.
2//!
3//! A Rust voxel engine. The CPU renderer is a clean-room per-pixel
4//! 3D-DDA over an 8³ brickmap ([`dda`] + [`dda_sprite`]); it reads the
5//! voxlap-compatible `.vxl` / KV6 / KFA formats from `roxlap-formats`
6//! but the rendering algorithm is not voxlap-derived. See
7//! `PORTING-RUST.md` at the workspace root for the project history.
8//!
9//! # World handedness and the horizontal mirror
10//!
11//! roxlap's world is **z-down**: `x` = east, `y` = north, `z` points
12//! *down* into the map. Physically the triple (east, north, up) is
13//! left-handed, so a faithfully-projected view is **horizontally
14//! mirrored** relative to a real camera at the same heading — the
15//! viewer's geometric *right* lands on screen-*left*. This is Voxlap's
16//! native convention; it is baked into the projection, the frustum
17//! cull, the scan loops, and every bit-exact oracle golden, and is
18//! reproduced deliberately. It is **not** a bug.
19//!
20//! The camera basis the engine actually renders with is
21//! right-handed in the `(right, down, forward)` sense
22//! (`right × down = +forward`). Build it with
23//! [`Camera::from_yaw_pitch`], [`Camera::orbit`], or
24//! [`Camera::look_at`] — never by rotating [`Camera::default`], whose
25//! placeholder basis is left-handed and will make the sprite cull
26//! reject every sprite.
27//!
28//! ## I want an un-mirrored world
29//!
30//! Do **not** "fix" the mirror by negating `right` in the basis. That
31//! flips the chirality to `right × down = -forward`; the world still
32//! renders, but the sprite frustum cull then rejects every sprite
33//! (and you diverge from the oracle goldens). The mirror is in the
34//! projection, not the basis.
35//!
36//! Handle it on the **consumer side** instead — pick one and stay
37//! consistent:
38//!
39//! - mirror a single world axis in your scene → world mapping (e.g.
40//! negate world-x when you place content), or
41//! - negate your yaw input so headings sweep the opposite way.
42//!
43//! Either re-establishes the chirality your project expects without
44//! touching the engine. (A true engine-side de-mirror would mean
45//! negating screen-x in *both* the grid raycaster and the sprite
46//! rasteriser while preserving the cull's normal winding — a large,
47//! golden-breaking change that diverges from Voxlap, and is out of
48//! scope here.)
49
50mod camera;
51pub mod camera_math;
52pub mod dda;
53pub mod dda_sprite;
54mod engine;
55pub(crate) mod fixed;
56pub mod grid_view;
57pub mod kfa_draw;
58pub mod opticast;
59pub mod raster_target;
60pub mod ray_aabb;
61pub mod sky;
62pub mod world_lighting;
63pub mod world_query;
64
65pub use camera::Camera;
66pub use dda::{
67 effective_mip, pixel_ray, render_dda, render_dda_parallel, BrickCache, DdaEnv, PixelSink,
68 RasterSink,
69};
70pub use dda_sprite::{draw_sprite_dda, draw_sprite_dense, ClipFlipbook, SpriteDense};
71pub use engine::{Engine, LightSrc, DEFAULT_KV6COL};
72pub use grid_view::{ChunkGrid, GridView};
73pub use opticast::OpticastSettings;
74pub use world_lighting::{
75 apply_lighting_with_cache, update_lighting, update_lighting_chunk, EstNormCache,
76};