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