pub struct GridTransform {
pub origin: DVec3,
pub rotation: DQuat,
}Expand description
f64 world placement of one grid: position + orientation.
origin is the grid’s local-space origin in world coords —
chunk (0, 0, 0)’s (0, 0, 0) voxel maps to
origin + rotation * vec3(0, 0, 0) (i.e. just origin).
Voxel size is fixed at 1 world unit / voxel for v1.
Fields§
§origin: DVec3The grid’s local-space origin, in world coordinates.
rotation: DQuatThe grid’s orientation about origin.
Implementations§
Source§impl GridTransform
impl GridTransform
Sourcepub fn identity() -> Self
pub fn identity() -> Self
Identity transform at world origin. Useful as a default for the first grid added to an otherwise empty scene.
Examples found in repository?
examples/book_controller.rs (line 31)
29fn build_world() -> Scene {
30 let mut scene = Scene::new();
31 let id = scene.add_grid(GridTransform::identity());
32 let g = scene.grid_mut(id).expect("grid");
33 // Ground slab: surface plane at z = 100 (+z is down, so the
34 // slab fills downward).
35 g.set_rect(
36 IVec3::new(20, 20, 100),
37 IVec3::new(140, 140, 120),
38 Some(VoxColor::rgb(0x4d, 0x8a, 0x3a)),
39 );
40 // A 1-voxel ledge to step onto, and a wall to slide along.
41 g.set_rect(
42 IVec3::new(90, 20, 99),
43 IVec3::new(140, 140, 99),
44 Some(VoxColor::rgb(0x77, 0x66, 0x55)),
45 );
46 g.set_rect(
47 IVec3::new(60, 70, 60),
48 IVec3::new(62, 140, 99),
49 Some(VoxColor::rgb(0x88, 0x44, 0x44)),
50 );
51 // A water curtain the veto lets the body wade through. Two
52 // format facts (both pinned as engine tests): pass-through
53 // geometry works up to 2 voxels thick — thicker walls grow a
54 // colourless UnexposedSolid core no veto can classify — and
55 // must sit ≥ 1 voxel inside the chunk (edge voxels lose their
56 // side colours).
57 g.set_rect(IVec3::new(40, 40, 80), IVec3::new(41, 60, 99), Some(WATER));
58 scene
59}Sourcepub fn at(origin: DVec3) -> Self
pub fn at(origin: DVec3) -> Self
Axis-aligned grid placed at origin with no rotation.
Examples found in repository?
examples/book_scene_graph.rs (line 87)
83fn main() {
84 // ANCHOR: scene_grids
85 let mut scene = Scene::new();
86 // A static "world" grid at the origin…
87 let ground_id = scene.add_grid(GridTransform::at(DVec3::ZERO));
88 // …and a second grid placed and rotated independently — its own
89 // f64 world position + quaternion, same chunked voxel payload.
90 let ship_id = scene.add_grid(GridTransform {
91 origin: DVec3::new(300.0, -80.0, -40.0),
92 rotation: DQuat::from_rotation_z(0.5),
93 });
94 // Object grids should not paint their own (grid-local, rotating)
95 // sky — leave the sky to the world grid.
96 scene.grid_mut(ship_id).expect("just added").render_sky = false;
97 // ANCHOR_END: scene_grids
98
99 // ANCHOR: edits
100 let ground = scene.grid_mut(ground_id).expect("just added");
101 // Solid slab: grid-local voxel coords, inclusive on both ends,
102 // decomposed across as many chunks as it spans (here 4×4).
103 ground.set_rect(
104 IVec3::new(-200, -200, 200),
105 IVec3::new(199, 199, 254),
106 Some(GRASS),
107 );
108 // `Some(colour)` inserts, `None` carves back to air.
109 ground.set_sphere(IVec3::new(0, 0, 195), 12, Some(STONE));
110 ground.set_rect(IVec3::new(-3, -200, 190), IVec3::new(3, 199, 196), None);
111 // ANCHOR_END: edits
112
113 // ANCHOR: queries
114 // Solid tests: inside the slab, then inside the carved tunnel.
115 assert!(ground.voxel_solid(IVec3::new(0, 0, 210)));
116 assert!(!ground.voxel_solid(IVec3::new(0, 100, 193)));
117 // Colour queries answer on surface voxels; deep interior cells
118 // are untextured in the slab format and read as `None`.
119 assert_eq!(ground.voxel_color(IVec3::new(50, 50, 200)), Some(GRASS));
120 // ANCHOR_END: queries
121
122 // ANCHOR: recolour
123 // GOTCHA: inserting over already-solid voxels does NOT repaint
124 // them — span insertion only fills air. Recolour = carve, then
125 // insert.
126 let (lo, hi) = (IVec3::new(20, 20, 200), IVec3::new(24, 24, 204));
127 ground.set_rect(lo, hi, Some(RED));
128 assert_eq!(ground.voxel_color(IVec3::new(22, 22, 200)), Some(GRASS)); // unchanged!
129 ground.set_rect(lo, hi, None); // carve…
130 ground.set_rect(lo, hi, Some(RED)); // …then insert
131 assert_eq!(ground.voxel_color(IVec3::new(22, 22, 200)), Some(RED));
132 // ANCHOR_END: recolour
133
134 // ANCHOR: colfunc
135 // A carve exposes fresh interior walls; the plain edits paint
136 // them colour 0 (black). The `_with_colfunc` variants ask a
137 // closure instead — it sees grid-local coordinates, so gradients
138 // stay continuous across chunk seams. Here: a crater whose walls
139 // darken with depth.
140 ground.set_sphere_with_colfunc(IVec3::new(60, 60, 200), 8, SpanOp::Carve, |_x, _y, z| {
141 let depth = (z - 192).clamp(0, 15) as u8;
142 VoxColor::rgb(0x6b, 0x40 + depth * 3, 0x2f)
143 });
144 // ANCHOR_END: colfunc
145
146 // ANCHOR: snapshot
147 // Name grids before saving: ids survive the round-trip, but the
148 // generator / store hooks are host code and cannot be serialised
149 // — the name is your key for rebinding them after a load.
150 scene.grid_mut(ground_id).expect("ground exists").name = Some("ground".into());
151 let bytes = scene.save_snapshot(); // versioned envelope
152 let restored = Scene::load_snapshot(&bytes).expect("self-authored snapshot");
153 assert_eq!(restored.grid_count(), 2);
154 let (_, ground2) = restored
155 .grids()
156 .find(|(_, g)| g.name.as_deref() == Some("ground"))
157 .expect("rebind by name");
158 assert_eq!(ground2.voxel_color(IVec3::new(22, 22, 200)), Some(RED));
159 // ANCHOR_END: snapshot
160
161 // ANCHOR: streaming
162 // Streaming: attach a generator + radii to a grid, then pump once
163 // per frame with the camera's world position. Chunks within
164 // `r_active` stream in; chunks beyond `r_evict` drop out; the band
165 // between is hysteresis so a camera hovering on a boundary
166 // doesn't thrash.
167 let stream_id = scene.add_grid(GridTransform::at(DVec3::new(0.0, 4096.0, 0.0)));
168 let store = Arc::new(MemoryStore::default());
169 let grid = scene.grid_mut(stream_id).expect("just added");
170 grid.set_generator(Some(Arc::new(FloorGenerator)));
171 grid.set_chunk_store(Some(store));
172 grid.stream_radius = StreamRadius::new(256.0, 384.0);
173
174 let camera_near = DVec3::new(0.0, 4096.0, 100.0);
175 scene.pump_streaming_sync(camera_near); // real games: `pump_streaming`
176 let grid = scene.grid(stream_id).expect("still there");
177 assert!(grid.chunk_count() > 0); // floor streamed in around the camera
178 assert!(grid.voxel_solid(IVec3::new(5, 5, 240)));
179 // ANCHOR_END: streaming
180
181 // ANCHOR: streaming_edit
182 // Edit the streamed floor, walk far away, come back. The active
183 // set follows the camera: the old region evicts (edited chunks
184 // are handed to the ChunkStore first) while a fresh set streams
185 // in around the new position. On return the store wins over the
186 // generator, so the edit survives; without a store, eviction
187 // would silently revert the chunk to generator output.
188 scene
189 .grid_mut(stream_id)
190 .expect("still there")
191 .set_voxel(IVec3::new(5, 5, 240), None); // dig a hole
192 scene.pump_streaming_sync(camera_near + DVec3::new(0.0, 100_000.0, 0.0));
193 let grid = scene.grid(stream_id).expect("still there");
194 assert!(grid.chunk(IVec3::ZERO).is_none()); // home chunk evicted…
195 assert!(grid.chunk_count() > 0); // …but the far region streamed in
196 scene.pump_streaming_sync(camera_near);
197 let grid = scene.grid(stream_id).expect("re-streamed");
198 // The hole survived evict + re-stream.
199 assert!(!grid.voxel_solid(IVec3::new(5, 5, 240)));
200 // ANCHOR_END: streaming_edit
201
202 println!("book_scene_graph: all scene-graph assertions hold");
203}Trait Implementations§
Source§impl Clone for GridTransform
impl Clone for GridTransform
Source§fn clone(&self) -> GridTransform
fn clone(&self) -> GridTransform
Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moreimpl Copy for GridTransform
Source§impl Debug for GridTransform
impl Debug for GridTransform
Source§impl Default for GridTransform
impl Default for GridTransform
Source§impl<'de> Deserialize<'de> for GridTransform
impl<'de> Deserialize<'de> for GridTransform
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read more
Source§impl PartialEq for GridTransform
impl PartialEq for GridTransform
Source§fn eq(&self, other: &GridTransform) -> bool
fn eq(&self, other: &GridTransform) -> bool
Tests for
self and other values to be equal, and is used by ==.Source§impl Serialize for GridTransform
impl Serialize for GridTransform
impl StructuralPartialEq for GridTransform
Auto Trait Implementations§
impl Freeze for GridTransform
impl RefUnwindSafe for GridTransform
impl Send for GridTransform
impl Sync for GridTransform
impl Unpin for GridTransform
impl UnsafeUnpin for GridTransform
impl UnwindSafe for GridTransform
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more