pub struct SceneWorld { /* private fields */ }Expand description
Native two-archetype ECS: render-only and render+velocity. No external ECS or locks. IDs index a location table; row compaction always repairs the moved entity’s location.
Implementations§
Source§impl SceneWorld
impl SceneWorld
Sourcepub fn new(limits: SceneLimits) -> Result<Self, RenderError>
pub fn new(limits: SceneLimits) -> Result<Self, RenderError>
Reserve bounded columns after validating the CPU budget.
Examples found in repository?
16fn sample(count: u32, binding: RenderBinding) -> Result<(u128, u128, u64)> {
17 let limits = SceneLimits {
18 max_entities: count,
19 max_snapshot_instances: count,
20 max_snapshots: 1,
21 managed_cpu_bytes: 512 * 1024 * 1024,
22 };
23 let bytes = limits.reservation_bytes()?;
24 let mut world = SceneWorld::new(limits)?;
25 let mut entities = Vec::with_capacity(count as usize);
26 let started = Instant::now();
27 for _ in 0..count {
28 entities.push(world.spawn(black_box(Transform::default()), black_box(binding), None)?);
29 }
30 let initial = started.elapsed().as_nanos();
31 let started = Instant::now();
32 for id in entities.drain(..) {
33 world.despawn(black_box(id))?;
34 }
35 for _ in 0..count {
36 entities.push(world.spawn(black_box(Transform::default()), black_box(binding), None)?);
37 }
38 let reuse = started.elapsed().as_nanos();
39 black_box((&world, &entities));
40 assert_eq!(world.len(), count as usize);
41 Ok((initial, reuse, bytes))
42}More examples
15fn main() -> Result<(), Box<dyn std::error::Error>> {
16 // Opaque asset identities only; this example qualifies CPU scene ownership, not drawing.
17 let mut assets = ResourceArena::new(RenderLimits::default())?;
18 let binding = RenderBinding {
19 mesh: assets.insert((), 1)?,
20 material: assets.insert((), 1)?,
21 tint: [1.0; 4],
22 animation: 0,
23 morph: 0,
24 };
25 let mut world = SceneWorld::new(SceneLimits {
26 max_entities: 64,
27 max_snapshot_instances: 64,
28 ..Default::default()
29 })?;
30 let mut first = None;
31 for i in 0..64 {
32 let id = world.spawn(
33 Transform::default().with_position([i as f32, 0.0, 0.0])?,
34 binding,
35 Some(Velocity::new([1.0, 0.0, 0.0])?),
36 )?;
37 first = first.or(Some(id));
38 }
39 let before = world.snapshot()?;
40 world.step_velocity(0.016)?;
41 let after = world.snapshot()?;
42 assert_eq!(before.instances()[0].transform.position()[0], 0.0);
43 assert_eq!(after.instances()[0].transform.position()[0], 0.016);
44 let mut commands = SceneCommands::new(8)?;
45 if let Some(first) = first {
46 commands.push(SceneCommand::SetVelocity(first, None))?;
47 }
48 for outcome in commands.apply(&mut world)? {
49 outcome?;
50 }
51 println!(
52 "entities={} owned_snapshots=2 moving_rows={}",
53 world.len(),
54 world.moving_columns().entities.len()
55 );
56 Ok(())
57}Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Live entities, bounded by the identity slot capacity.
Examples found in repository?
16fn sample(count: u32, binding: RenderBinding) -> Result<(u128, u128, u64)> {
17 let limits = SceneLimits {
18 max_entities: count,
19 max_snapshot_instances: count,
20 max_snapshots: 1,
21 managed_cpu_bytes: 512 * 1024 * 1024,
22 };
23 let bytes = limits.reservation_bytes()?;
24 let mut world = SceneWorld::new(limits)?;
25 let mut entities = Vec::with_capacity(count as usize);
26 let started = Instant::now();
27 for _ in 0..count {
28 entities.push(world.spawn(black_box(Transform::default()), black_box(binding), None)?);
29 }
30 let initial = started.elapsed().as_nanos();
31 let started = Instant::now();
32 for id in entities.drain(..) {
33 world.despawn(black_box(id))?;
34 }
35 for _ in 0..count {
36 entities.push(world.spawn(black_box(Transform::default()), black_box(binding), None)?);
37 }
38 let reuse = started.elapsed().as_nanos();
39 black_box((&world, &entities));
40 assert_eq!(world.len(), count as usize);
41 Ok((initial, reuse, bytes))
42}More examples
15fn main() -> Result<(), Box<dyn std::error::Error>> {
16 // Opaque asset identities only; this example qualifies CPU scene ownership, not drawing.
17 let mut assets = ResourceArena::new(RenderLimits::default())?;
18 let binding = RenderBinding {
19 mesh: assets.insert((), 1)?,
20 material: assets.insert((), 1)?,
21 tint: [1.0; 4],
22 animation: 0,
23 morph: 0,
24 };
25 let mut world = SceneWorld::new(SceneLimits {
26 max_entities: 64,
27 max_snapshot_instances: 64,
28 ..Default::default()
29 })?;
30 let mut first = None;
31 for i in 0..64 {
32 let id = world.spawn(
33 Transform::default().with_position([i as f32, 0.0, 0.0])?,
34 binding,
35 Some(Velocity::new([1.0, 0.0, 0.0])?),
36 )?;
37 first = first.or(Some(id));
38 }
39 let before = world.snapshot()?;
40 world.step_velocity(0.016)?;
41 let after = world.snapshot()?;
42 assert_eq!(before.instances()[0].transform.position()[0], 0.0);
43 assert_eq!(after.instances()[0].transform.position()[0], 0.016);
44 let mut commands = SceneCommands::new(8)?;
45 if let Some(first) = first {
46 commands.push(SceneCommand::SetVelocity(first, None))?;
47 }
48 for outcome in commands.apply(&mut world)? {
49 outcome?;
50 }
51 println!(
52 "entities={} owned_snapshots=2 moving_rows={}",
53 world.len(),
54 world.moving_columns().entities.len()
55 );
56 Ok(())
57}Sourcepub fn spawn(
&mut self,
transform: Transform,
binding: RenderBinding,
velocity: Option<Velocity>,
) -> Result<EntityId, RenderError>
pub fn spawn( &mut self, transform: Transform, binding: RenderBinding, velocity: Option<Velocity>, ) -> Result<EntityId, RenderError>
Spawn a validated instance in the matching archetype. Failure makes no structural change. Slot admission is constant-time through a bounded free list; reuse order is unspecified.
Examples found in repository?
16fn sample(count: u32, binding: RenderBinding) -> Result<(u128, u128, u64)> {
17 let limits = SceneLimits {
18 max_entities: count,
19 max_snapshot_instances: count,
20 max_snapshots: 1,
21 managed_cpu_bytes: 512 * 1024 * 1024,
22 };
23 let bytes = limits.reservation_bytes()?;
24 let mut world = SceneWorld::new(limits)?;
25 let mut entities = Vec::with_capacity(count as usize);
26 let started = Instant::now();
27 for _ in 0..count {
28 entities.push(world.spawn(black_box(Transform::default()), black_box(binding), None)?);
29 }
30 let initial = started.elapsed().as_nanos();
31 let started = Instant::now();
32 for id in entities.drain(..) {
33 world.despawn(black_box(id))?;
34 }
35 for _ in 0..count {
36 entities.push(world.spawn(black_box(Transform::default()), black_box(binding), None)?);
37 }
38 let reuse = started.elapsed().as_nanos();
39 black_box((&world, &entities));
40 assert_eq!(world.len(), count as usize);
41 Ok((initial, reuse, bytes))
42}More examples
15fn main() -> Result<(), Box<dyn std::error::Error>> {
16 // Opaque asset identities only; this example qualifies CPU scene ownership, not drawing.
17 let mut assets = ResourceArena::new(RenderLimits::default())?;
18 let binding = RenderBinding {
19 mesh: assets.insert((), 1)?,
20 material: assets.insert((), 1)?,
21 tint: [1.0; 4],
22 animation: 0,
23 morph: 0,
24 };
25 let mut world = SceneWorld::new(SceneLimits {
26 max_entities: 64,
27 max_snapshot_instances: 64,
28 ..Default::default()
29 })?;
30 let mut first = None;
31 for i in 0..64 {
32 let id = world.spawn(
33 Transform::default().with_position([i as f32, 0.0, 0.0])?,
34 binding,
35 Some(Velocity::new([1.0, 0.0, 0.0])?),
36 )?;
37 first = first.or(Some(id));
38 }
39 let before = world.snapshot()?;
40 world.step_velocity(0.016)?;
41 let after = world.snapshot()?;
42 assert_eq!(before.instances()[0].transform.position()[0], 0.0);
43 assert_eq!(after.instances()[0].transform.position()[0], 0.016);
44 let mut commands = SceneCommands::new(8)?;
45 if let Some(first) = first {
46 commands.push(SceneCommand::SetVelocity(first, None))?;
47 }
48 for outcome in commands.apply(&mut world)? {
49 outcome?;
50 }
51 println!(
52 "entities={} owned_snapshots=2 moving_rows={}",
53 world.len(),
54 world.moving_columns().entities.len()
55 );
56 Ok(())
57}Sourcepub fn despawn(&mut self, id: EntityId) -> Result<(), RenderError>
pub fn despawn(&mut self, id: EntityId) -> Result<(), RenderError>
Remove without invalidating other identities; stale handles never alias a later spawn.
Examples found in repository?
16fn sample(count: u32, binding: RenderBinding) -> Result<(u128, u128, u64)> {
17 let limits = SceneLimits {
18 max_entities: count,
19 max_snapshot_instances: count,
20 max_snapshots: 1,
21 managed_cpu_bytes: 512 * 1024 * 1024,
22 };
23 let bytes = limits.reservation_bytes()?;
24 let mut world = SceneWorld::new(limits)?;
25 let mut entities = Vec::with_capacity(count as usize);
26 let started = Instant::now();
27 for _ in 0..count {
28 entities.push(world.spawn(black_box(Transform::default()), black_box(binding), None)?);
29 }
30 let initial = started.elapsed().as_nanos();
31 let started = Instant::now();
32 for id in entities.drain(..) {
33 world.despawn(black_box(id))?;
34 }
35 for _ in 0..count {
36 entities.push(world.spawn(black_box(Transform::default()), black_box(binding), None)?);
37 }
38 let reuse = started.elapsed().as_nanos();
39 black_box((&world, &entities));
40 assert_eq!(world.len(), count as usize);
41 Ok((initial, reuse, bytes))
42}Sourcepub fn transform(&self, id: EntityId) -> Result<Transform, RenderError>
pub fn transform(&self, id: EntityId) -> Result<Transform, RenderError>
Read the current validated transform by stable identity.
Sourcepub fn set_transform(
&mut self,
id: EntityId,
value: Transform,
) -> Result<(), RenderError>
pub fn set_transform( &mut self, id: EntityId, value: Transform, ) -> Result<(), RenderError>
Replace a validated transform without moving its row or binding.
Sourcepub fn set_velocity(
&mut self,
id: EntityId,
velocity: Option<Velocity>,
) -> Result<(), RenderError>
pub fn set_velocity( &mut self, id: EntityId, velocity: Option<Velocity>, ) -> Result<(), RenderError>
Add/remove velocity through explicit archetype migration, preserving entity identity.
Sourcepub fn moving_columns(&mut self) -> MovingColumns<'_>
pub fn moving_columns(&mut self) -> MovingColumns<'_>
Borrow disjoint aligned transform/velocity columns. Structural mutation requires releasing them.
Examples found in repository?
15fn main() -> Result<(), Box<dyn std::error::Error>> {
16 // Opaque asset identities only; this example qualifies CPU scene ownership, not drawing.
17 let mut assets = ResourceArena::new(RenderLimits::default())?;
18 let binding = RenderBinding {
19 mesh: assets.insert((), 1)?,
20 material: assets.insert((), 1)?,
21 tint: [1.0; 4],
22 animation: 0,
23 morph: 0,
24 };
25 let mut world = SceneWorld::new(SceneLimits {
26 max_entities: 64,
27 max_snapshot_instances: 64,
28 ..Default::default()
29 })?;
30 let mut first = None;
31 for i in 0..64 {
32 let id = world.spawn(
33 Transform::default().with_position([i as f32, 0.0, 0.0])?,
34 binding,
35 Some(Velocity::new([1.0, 0.0, 0.0])?),
36 )?;
37 first = first.or(Some(id));
38 }
39 let before = world.snapshot()?;
40 world.step_velocity(0.016)?;
41 let after = world.snapshot()?;
42 assert_eq!(before.instances()[0].transform.position()[0], 0.0);
43 assert_eq!(after.instances()[0].transform.position()[0], 0.016);
44 let mut commands = SceneCommands::new(8)?;
45 if let Some(first) = first {
46 commands.push(SceneCommand::SetVelocity(first, None))?;
47 }
48 for outcome in commands.apply(&mut world)? {
49 outcome?;
50 }
51 println!(
52 "entities={} owned_snapshots=2 moving_rows={}",
53 world.len(),
54 world.moving_columns().entities.len()
55 );
56 Ok(())
57}Sourcepub fn step_velocity(&mut self, dt: f32) -> Result<(), RenderError>
pub fn step_velocity(&mut self, dt: f32) -> Result<(), RenderError>
Integrate local velocity with a bounded timestep; validate every candidate before committing any.
Examples found in repository?
15fn main() -> Result<(), Box<dyn std::error::Error>> {
16 // Opaque asset identities only; this example qualifies CPU scene ownership, not drawing.
17 let mut assets = ResourceArena::new(RenderLimits::default())?;
18 let binding = RenderBinding {
19 mesh: assets.insert((), 1)?,
20 material: assets.insert((), 1)?,
21 tint: [1.0; 4],
22 animation: 0,
23 morph: 0,
24 };
25 let mut world = SceneWorld::new(SceneLimits {
26 max_entities: 64,
27 max_snapshot_instances: 64,
28 ..Default::default()
29 })?;
30 let mut first = None;
31 for i in 0..64 {
32 let id = world.spawn(
33 Transform::default().with_position([i as f32, 0.0, 0.0])?,
34 binding,
35 Some(Velocity::new([1.0, 0.0, 0.0])?),
36 )?;
37 first = first.or(Some(id));
38 }
39 let before = world.snapshot()?;
40 world.step_velocity(0.016)?;
41 let after = world.snapshot()?;
42 assert_eq!(before.instances()[0].transform.position()[0], 0.0);
43 assert_eq!(after.instances()[0].transform.position()[0], 0.016);
44 let mut commands = SceneCommands::new(8)?;
45 if let Some(first) = first {
46 commands.push(SceneCommand::SetVelocity(first, None))?;
47 }
48 for outcome in commands.apply(&mut world)? {
49 outcome?;
50 }
51 println!(
52 "entities={} owned_snapshots=2 moving_rows={}",
53 world.len(),
54 world.moving_columns().entities.len()
55 );
56 Ok(())
57}Sourcepub fn snapshot(&self) -> Result<SceneSnapshot, RenderError>
pub fn snapshot(&self) -> Result<SceneSnapshot, RenderError>
Extract owned instances; rejects excess before allocating the snapshot. A renderer must resolve asset identities before uploading or submitting a draw.
Examples found in repository?
15fn main() -> Result<(), Box<dyn std::error::Error>> {
16 // Opaque asset identities only; this example qualifies CPU scene ownership, not drawing.
17 let mut assets = ResourceArena::new(RenderLimits::default())?;
18 let binding = RenderBinding {
19 mesh: assets.insert((), 1)?,
20 material: assets.insert((), 1)?,
21 tint: [1.0; 4],
22 animation: 0,
23 morph: 0,
24 };
25 let mut world = SceneWorld::new(SceneLimits {
26 max_entities: 64,
27 max_snapshot_instances: 64,
28 ..Default::default()
29 })?;
30 let mut first = None;
31 for i in 0..64 {
32 let id = world.spawn(
33 Transform::default().with_position([i as f32, 0.0, 0.0])?,
34 binding,
35 Some(Velocity::new([1.0, 0.0, 0.0])?),
36 )?;
37 first = first.or(Some(id));
38 }
39 let before = world.snapshot()?;
40 world.step_velocity(0.016)?;
41 let after = world.snapshot()?;
42 assert_eq!(before.instances()[0].transform.position()[0], 0.0);
43 assert_eq!(after.instances()[0].transform.position()[0], 0.016);
44 let mut commands = SceneCommands::new(8)?;
45 if let Some(first) = first {
46 commands.push(SceneCommand::SetVelocity(first, None))?;
47 }
48 for outcome in commands.apply(&mut world)? {
49 outcome?;
50 }
51 println!(
52 "entities={} owned_snapshots=2 moving_rows={}",
53 world.len(),
54 world.moving_columns().entities.len()
55 );
56 Ok(())
57}