Skip to main content

Crate roxlap_core

Crate roxlap_core 

Source
Expand description

roxlap engine core.

A Rust voxel engine. The CPU renderer is a clean-room per-pixel 3D-DDA over an 8³ brickmap (dda + dda_sprite); it reads the voxlap-compatible .vxl / KV6 / KFA formats from roxlap-formats but the rendering algorithm is not voxlap-derived. See PORTING-RUST.md at the workspace root for the project history.

§World handedness and the horizontal mirror

roxlap’s world is z-down: x = east, y = north, z points down into the map. Physically the triple (east, north, up) is left-handed, so a faithfully-projected view is horizontally mirrored relative to a real camera at the same heading — the viewer’s geometric right lands on screen-left. This is Voxlap’s native convention; it is baked into the projection, the frustum cull, the scan loops, and every bit-exact oracle golden, and is reproduced deliberately. It is not a bug.

The camera basis the engine actually renders with is right-handed in the (right, down, forward) sense (right × down = +forward). Build it with Camera::from_yaw_pitch, Camera::orbit, or Camera::look_at — never by rotating Camera::default, whose placeholder basis is left-handed and will make the sprite cull reject every sprite.

§I want an un-mirrored world

Do not “fix” the mirror by negating right in the basis. That flips the chirality to right × down = -forward; the world still renders, but the sprite frustum cull then rejects every sprite (and you diverge from the oracle goldens). The mirror is in the projection, not the basis.

Handle it on the consumer side instead — pick one and stay consistent:

  • mirror a single world axis in your scene → world mapping (e.g. negate world-x when you place content), or
  • negate your yaw input so headings sweep the opposite way.

Either re-establishes the chirality your project expects without touching the engine. (A true engine-side de-mirror would mean negating screen-x in both the grid raycaster and the sprite rasteriser while preserving the cull’s normal winding — a large, golden-breaking change that diverges from Voxlap, and is out of scope here.)

Re-exports§

pub use dda::effective_mip;
pub use dda::pixel_ray;
pub use dda::render_dda;
pub use dda::render_dda_parallel;
pub use dda::render_sky_fill;
pub use dda::BrickCache;
pub use dda::DdaEnv;
pub use dda::PixelSink;
pub use dda::RasterSink;
pub use dda_sprite::draw_sprite_dda;
pub use dda_sprite::draw_sprite_dda_shaded;
pub use dda_sprite::draw_sprite_dense;
pub use dda_sprite::draw_sprite_dense_shaded;
pub use dda_sprite::ClipFlipbook;
pub use dda_sprite::SpriteDense;
pub use dda_sprite::SpriteShade;
pub use grid_view::ChunkGrid;
pub use grid_view::GridView;
pub use opticast::OpticastSettings;
pub use world_lighting::apply_lighting_with_cache;
pub use world_lighting::update_lighting;
pub use world_lighting::update_lighting_chunk;
pub use world_lighting::EstNormCache;

Modules§

camera_math
Per-frame camera state for the pinhole projection the renderer uses.
dda
Per-pixel 3D-DDA + brickmap CPU renderer (Substage DDA).
dda_sprite
Clean-room KV6 sprite raycaster for the DDA backend (Substage DDA.8).
grid_view
Per-frame voxel-world borrow shape.
kfa_draw
KFA (animated kv6) bone solver — the bone-transform helpers genperp, mat0, and setlimb.
opticast
Per-frame render settings shared by the CPU renderer.
raster_target
RasterTarget — a Copy borrowed view of the framebuffer + zbuffer as raw pointers, the compositing primitive shared by the DDA terrain renderer (crate::dda) and the DDA sprite raycaster (crate::dda_sprite).
ray_aabb
S1.1 — ray ↔ axis-aligned bounding box clip helper.
sky
Sky-texture resource for the textured-sky path.
world_lighting
World-voxel lighting bake.
world_query
Per-voxel world queries against a .vxl column-slab world.

Structs§

Camera
Camera state. All vectors are in voxel-world units (1 unit = 1 voxel); the basis is right-handed with down aligned to +z (i.e. z grows downward into the map, matching voxlap’s coordinate system).
Engine
Voxel engine state.
LightSrc
One point light source for sprite (and, eventually, world) lighting. Mirror of voxlap’s lightsrc_t (voxlap5.h): position, squared reach radius, and intensity scale. The lighting math reads r2 not r, matching voxlap’s vx5.lightsrc[i].r2-keyed range check.

Constants§

DEFAULT_KV6COL
Voxlap’s vx5.kv6col default — mid-grey, equal R/G/B so the sprite update_reflects nolighta optimisation kicks in.