1use fast_mesh_bvh::{Aabb, BuildOptions, Bvh, BvhBuild, UpdatePolicy};
4use fast_mesh_store::{ChangeSet, ChannelDesc, Mesh, Remap, StoreError, Transaction, VertexId};
5
6use crate::fields::{ColorState, CurvField, Field, FieldHook, FieldUnit, ThickField};
7use crate::history::{Change, Done, History};
8use crate::id::SlotMap;
9use crate::normals::{NormalBuild, NormalState};
10use crate::query::{CachedBox, ClosestCandidate, RayCandidate};
11use crate::report::Report;
12use crate::sections::{Section, SectionHook};
13use crate::{FieldId, MeshChanges, MeshId, Placement, Result, SceneError, SectionId, SubscriberId};
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
17pub enum UpdateMode {
18 #[default]
20 Eager,
21 Lazy,
23 Manual,
25}
26
27#[derive(Debug, Clone, Copy, PartialEq, Default)]
29pub struct MeshOptions {
30 pub build: BuildOptions,
32 pub bvh_policy: UpdatePolicy,
34 pub mode: UpdateMode,
36 pub placement: Placement,
38 pub defer_bvh: bool,
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq)]
49pub struct SceneOptions {
50 pub history_budget: usize,
52}
53
54impl Default for SceneOptions {
55 fn default() -> Self {
57 SceneOptions {
58 history_budget: 256 << 20,
59 }
60 }
61}
62
63pub(crate) struct Entry {
65 pub(crate) mesh: Mesh,
66 pub(crate) bvh: Bvh,
67 pub(crate) placement: Placement,
68 pub(crate) mode: UpdateMode,
69 pub(crate) pending: Option<ChangeSet>,
72 pub(crate) rebuild: bool,
76 pub(crate) reports: Vec<Report>,
79 pub(crate) hooks: Vec<FieldHook>,
82 pub(crate) section_hooks: Vec<SectionHook>,
84 pub(crate) coloring: Option<ColorState>,
86 pub(crate) normals: Option<NormalState>,
88 pub(crate) content: u64,
92 pub(crate) wbox: Option<CachedBox>,
95}
96
97impl Entry {
98 pub(crate) fn flag_unknown(&mut self) {
104 self.pending = Some(ChangeSet::default());
105 self.rebuild = true;
106 self.wbox = None;
107 self.report_everything();
108 }
109
110 pub(crate) fn report_everything(&mut self) {
115 self.content += 1;
116 for r in &mut self.reports {
117 r.changes = None;
118 r.colors_dirty = None;
119 r.normals_dirty = None;
120 }
121 if let Some(ns) = &mut self.normals {
122 ns.mark_all();
123 }
124 for h in &mut self.hooks {
125 h.changes = None;
126 }
127 for h in &mut self.section_hooks {
128 h.changes = None;
129 }
130 }
131
132 pub(crate) fn report_placement(&mut self) {
135 for r in &mut self.reports {
136 r.placement_changed = true;
137 }
138 for h in &mut self.hooks {
139 h.placement_changed = true;
140 }
141 for h in &mut self.section_hooks {
142 h.placement_changed = true;
143 }
144 }
145
146 pub(crate) fn report_colors(&mut self, ids: Option<&[VertexId]>) {
148 for r in &mut self.reports {
149 r.colors_changed(ids);
150 }
151 }
152
153 pub(crate) fn report_field(&mut self, id: FieldId) {
155 for r in &mut self.reports {
156 r.field_changed(id);
157 }
158 }
159
160 pub(crate) fn report_section(&mut self, id: SectionId) {
163 for r in &mut self.reports {
164 r.section_changed(id);
165 }
166 }
167
168 fn report_channel(&mut self, name: &str) {
170 for r in &mut self.reports {
171 r.channel_written(name);
172 }
173 }
174
175 pub(crate) fn record_changes(&mut self, changes: &ChangeSet) {
179 self.content += 1;
180 match &mut self.pending {
181 Some(p) => p.merge(changes),
182 None => self.pending = Some(changes.clone()),
183 }
184 for r in &mut self.reports {
185 r.merge(changes);
186 }
187 for name in &changes.channels_toggled {
188 self.report_channel(name);
189 }
190 for h in &mut self.hooks {
191 if let Some(c) = &mut h.changes {
192 c.merge(changes);
193 }
194 }
195 for h in &mut self.section_hooks {
196 if let Some(c) = &mut h.changes {
197 c.merge(changes);
198 }
199 }
200 if let Some(ns) = &mut self.normals {
201 ns.record(changes, self.mesh.vertex_slots());
202 }
203 self.grow_colors(&changes.vertices_added);
206 }
207
208 pub(crate) fn is_current(&self) -> bool {
211 !self.rebuild && self.bvh.is_current(&self.mesh)
212 }
213
214 pub(crate) fn update_bvh(&mut self) -> Result<()> {
217 if self.rebuild {
218 #[cfg(test)]
219 fault::before_bvh_update()?;
220 #[cfg(test)]
221 fault::count_rebuild();
222 let mut bvh = Bvh::build(&self.mesh, self.bvh.options())?;
223 bvh.set_policy(*self.bvh.policy())?;
224 self.bvh = bvh;
225 self.rebuild = false;
226 self.pending = None;
227 return Ok(());
228 }
229 if self.bvh.is_current(&self.mesh) {
230 self.pending = None;
231 return Ok(());
232 }
233 #[cfg(test)]
234 fault::before_bvh_update()?;
235 debug_assert!(self.pending.is_some(), "stale BVH without pending changes");
241 let none = ChangeSet::default();
242 let changes = self.pending.as_ref().unwrap_or(&none);
243 self.bvh.update(&mut self.mesh, changes)?;
244 self.pending = None;
245 Ok(())
246 }
247
248 pub(crate) fn after_change(&mut self) {
253 if self.mode == UpdateMode::Eager {
254 let _ = self.update_bvh();
255 let _ = self.update_normals();
256 }
257 }
258}
259
260struct Subscriber {
262 id: SubscriberId,
263 removed: Vec<MeshChanges>,
265}
266
267#[derive(Debug)]
273pub struct MeshBuild {
274 mesh: Mesh,
275 options: MeshOptions,
276 bvh: BvhBuild,
277 normals: Option<NormalBuild>,
279}
280
281impl MeshBuild {
282 pub fn new(mesh: Mesh, options: MeshOptions) -> Result<MeshBuild> {
288 options.placement.validate()?;
289 options.bvh_policy.validate()?;
290 let bvh = BvhBuild::new(&mesh, &options.build)?;
291 Ok(MeshBuild {
292 mesh,
293 options,
294 bvh,
295 normals: None,
296 })
297 }
298
299 pub fn set_normals(&mut self, on: bool) {
304 if !on {
305 self.normals = None;
306 } else if self.normals.is_none() {
307 self.normals = Some(NormalBuild::new());
308 }
309 }
310
311 pub fn step(&mut self, budget: usize) -> Result<bool> {
318 if !self.bvh.is_done() {
319 self.bvh.step(&self.mesh, budget)?;
320 } else if let Some(n) = &mut self.normals {
321 n.step(&self.mesh, budget)?;
322 }
323 Ok(self.is_done())
324 }
325
326 pub fn is_done(&self) -> bool {
328 self.bvh.is_done() && self.normals.as_ref().is_none_or(NormalBuild::is_done)
329 }
330
331 pub fn normals(&self) -> Option<&[[f32; 3]]> {
334 self.normals
335 .as_ref()
336 .filter(|n| n.is_done())
337 .map(NormalBuild::normals)
338 }
339
340 pub fn mesh(&self) -> &Mesh {
342 &self.mesh
343 }
344}
345
346pub struct Scene {
348 pub(crate) entries: SlotMap<Entry>,
349 subscribers: Vec<Subscriber>,
352 next_subscriber: u64,
354 history: History,
356 pub(crate) fields: Vec<Field>,
358 pub(crate) thick: Vec<ThickField>,
360 pub(crate) curv: Vec<CurvField>,
362 pub(crate) next_field: u32,
364 pub(crate) sections: Vec<Section>,
366 pub(crate) next_section: u32,
368 pub(crate) defer_fields: bool,
370 pub(crate) field_interaction: Option<usize>,
372 pub(crate) field_unit: Option<FieldUnit>,
374 pub(crate) order_ray: Vec<RayCandidate>,
378 pub(crate) order_closest: Vec<ClosestCandidate>,
379 #[cfg(test)]
381 pub(crate) section_recomputes: usize,
382 #[cfg(test)]
384 pub(crate) section_reach_checks: usize,
385}
386
387impl Scene {
392 pub fn new(options: SceneOptions) -> Scene {
394 Scene {
395 entries: SlotMap::new(),
396 subscribers: vec![Subscriber {
397 id: SubscriberId::DEFAULT,
398 removed: Vec::new(),
399 }],
400 next_subscriber: SubscriberId::DEFAULT.0 + 1,
401 history: History::new(options.history_budget),
402 fields: Vec::new(),
403 thick: Vec::new(),
404 curv: Vec::new(),
405 next_field: 0,
406 sections: Vec::new(),
407 next_section: 0,
408 defer_fields: false,
409 field_interaction: None,
410 field_unit: None,
411 order_ray: Vec::new(),
412 order_closest: Vec::new(),
413 #[cfg(test)]
414 section_recomputes: 0,
415 #[cfg(test)]
416 section_reach_checks: 0,
417 }
418 }
419
420 pub(crate) fn entry_mut(&mut self, id: MeshId) -> Result<&mut Entry> {
421 self.entries.get_mut(id).ok_or(SceneError::UnknownMesh)
422 }
423
424 pub fn add_mesh(&mut self, mesh: Mesh, options: MeshOptions) -> Result<MeshId> {
434 self.drop_field_unit();
435 options.placement.validate()?;
436 options.bvh_policy.validate()?;
437 if !options.defer_bvh || options.mode == UpdateMode::Eager {
438 let bvh = Bvh::build(&mesh, &options.build)?;
439 return self.insert_mesh(mesh, bvh, options);
440 }
441 let bvh = Bvh::build(&Mesh::new(), &options.build)?;
444 let id = self.insert_mesh(mesh, bvh, options)?;
445 let entry = self.entry_mut(id)?;
446 entry.pending = Some(ChangeSet::default());
447 entry.rebuild = true;
448 Ok(id)
449 }
450
451 pub fn add_mesh_built(&mut self, mut build: MeshBuild) -> Result<MeshId> {
460 self.drop_field_unit();
461 while !build.step(usize::MAX)? {}
462 let MeshBuild {
463 mesh,
464 options,
465 bvh,
466 normals,
467 } = build;
468 let bvh = bvh.finish().ok_or(SceneError::Corrupted)?;
469 let normals = match normals {
470 Some(n) => Some(n.finish().ok_or(SceneError::Corrupted)?),
471 None => None,
472 };
473 let id = self.insert_mesh(mesh, bvh, options)?;
474 if let Some(n) = normals {
475 let entry = self.entry_mut(id)?;
476 entry.normals = Some(n);
477 entry.report_normals(None);
478 }
479 Ok(id)
480 }
481
482 fn insert_mesh(&mut self, mesh: Mesh, mut bvh: Bvh, options: MeshOptions) -> Result<MeshId> {
484 bvh.set_policy(options.bvh_policy)?;
485 self.entries.insert(Entry {
486 mesh,
487 bvh,
488 placement: options.placement,
489 mode: options.mode,
490 pending: None,
491 rebuild: false,
492 reports: vec![Report::added(); self.subscribers.len()],
493 hooks: Vec::new(),
494 section_hooks: Vec::new(),
495 coloring: None,
496 normals: None,
497 content: 0,
498 wbox: None,
499 })
500 }
501
502 pub fn remove_mesh(&mut self, id: MeshId) -> Result<Mesh> {
519 self.drop_field_unit();
520 self.entry(id)?;
521 for s in &mut self.subscribers {
523 s.removed
524 .try_reserve(1)
525 .map_err(|_| SceneError::Store(StoreError::OutOfMemory))?;
526 }
527 let kept_on = self.drop_fields_of(id);
528 self.drop_sections_of(id);
529 let mut entry = self.entries.remove(id).ok_or(SceneError::UnknownMesh)?;
530 self.history.forget(id, Some(&mut entry.mesh));
531 for (s, r) in self.subscribers.iter_mut().zip(&mut entry.reports) {
532 if !r.added {
533 s.removed.push(r.take(id, true));
534 }
535 }
536 self.run_eager_fields(Some(&kept_on));
538 Ok(entry.mesh)
539 }
540
541 pub fn edit<R, E: Into<SceneError>>(
569 &mut self,
570 id: MeshId,
571 f: impl FnOnce(&mut Transaction) -> std::result::Result<R, E>,
572 ) -> Result<R> {
573 self.drop_field_unit();
574 let entry = self.entries.get_mut(id).ok_or(SceneError::UnknownMesh)?;
575 self.history.reserve()?;
577 let mut tx = entry.mesh.begin_edit();
578 let r = f(&mut tx).map_err(Into::into)?;
580 let patch = tx.commit()?;
581 if patch.is_empty() {
582 return Ok(r);
583 }
584 entry.record_changes(patch.changes());
585 self.history
586 .record(&mut self.entries, Change::Edit(id, patch));
587 if let Some(entry) = self.entries.get_mut(id) {
588 entry.after_change();
589 }
590 self.run_eager(Some(&[id]));
591 Ok(r)
592 }
593
594 pub fn begin_step(&mut self) {
598 self.drop_field_unit();
599 self.history.begin();
600 }
601
602 pub fn end_step(&mut self) -> Result<()> {
609 self.drop_field_unit();
610 self.history.end(&mut self.entries)
611 }
612
613 pub fn cancel_step(&mut self) -> Result<()> {
623 self.drop_field_unit();
624 let done = self.history.cancel(&mut self.entries);
625 let done = self.after_corrupted(done)?;
626 self.absorb(done);
627 Ok(())
628 }
629
630 fn after_corrupted<T>(&mut self, r: Result<T>) -> Result<T> {
634 if r.as_ref().err() == Some(&SceneError::Corrupted) {
635 self.run_eager(None);
636 }
637 r
638 }
639
640 fn run_eager(&mut self, touched: Option<&[MeshId]>) {
643 self.run_eager_fields(touched);
644 self.run_eager_sections(touched);
645 }
646
647 pub fn undo(&mut self) -> Result<bool> {
671 self.drop_field_unit();
672 let done = self.history.undo(&mut self.entries);
673 let done = self.after_corrupted(done)?;
674 Ok(done.map(|d| self.absorb(d)).is_some())
675 }
676
677 pub fn redo(&mut self) -> Result<bool> {
684 self.drop_field_unit();
685 let done = self.history.redo(&mut self.entries);
686 let done = self.after_corrupted(done)?;
687 Ok(done.map(|d| self.absorb(d)).is_some())
688 }
689
690 pub fn can_undo(&self) -> bool {
693 self.history.can_undo()
694 }
695
696 pub fn can_redo(&self) -> bool {
698 self.history.can_redo()
699 }
700
701 pub fn clear_history(&mut self) -> Result<()> {
707 self.drop_field_unit();
708 self.history.clear(&mut self.entries);
709 Ok(())
710 }
711
712 fn absorb(&mut self, done: Vec<Done>) {
716 for (id, changes) in &done {
717 if let Some(e) = self.entries.get_mut(*id) {
718 match changes {
719 Some(c) => e.record_changes(c),
720 None => e.report_placement(),
721 }
722 }
723 }
724 for (id, _) in done.iter().filter(|(_, c)| c.is_some()) {
726 if let Some(e) = self.entries.get_mut(*id) {
727 e.after_change();
728 }
729 }
730 let touched: Vec<MeshId> = done.iter().map(|(id, _)| *id).collect();
731 self.run_eager(Some(&touched));
732 }
733
734 pub fn set_mode(&mut self, id: MeshId, mode: UpdateMode) -> Result<()> {
742 self.drop_field_unit();
743 let entry = self.entry_mut(id)?;
744 entry.mode = mode;
745 entry.after_change();
746 self.run_eager(Some(&[id]));
747 Ok(())
748 }
749
750 pub fn mode(&self, id: MeshId) -> Result<UpdateMode> {
755 Ok(self.entry(id)?.mode)
756 }
757
758 pub fn update(&mut self, id: MeshId) -> Result<()> {
771 self.drop_field_unit();
772 let entry = self.entry_mut(id)?;
773 let bvh = entry.update_bvh();
774 let normals = entry.update_normals();
775 bvh.and(normals)?;
776 self.run_eager_fields(Some(&[id]));
777 self.run_sections(|_| true, Some(&[id]))
778 }
779
780 pub fn flush(&mut self) -> Result<()> {
795 self.drop_field_unit();
796 let mut first = Ok(());
797 for (_, entry) in self.entries.iter_mut() {
798 if entry.mode != UpdateMode::Manual {
799 let bvh = entry.update_bvh();
800 let normals = entry.update_normals();
801 if first.is_ok() {
802 first = bvh.and(normals);
803 }
804 }
805 }
806 let r = self.run_fields(|mode| mode != UpdateMode::Manual, None);
807 if first.is_ok() {
808 first = r;
809 }
810 let r = self.run_sections(|mode| mode != UpdateMode::Manual, None);
811 if first.is_ok() {
812 first = r;
813 }
814 first
815 }
816
817 pub fn take_changes(&mut self) -> Vec<MeshChanges> {
826 self.drop_field_unit();
827 self.take_at(0)
829 }
830
831 pub fn subscribe(&mut self) -> SubscriberId {
840 self.drop_field_unit();
841 let id = SubscriberId(self.next_subscriber);
842 self.next_subscriber += 1;
843 for (_, entry) in self.entries.iter_mut() {
844 let mut report = Report::clean();
845 if entry.coloring.is_some() {
846 report.colors_dirty = None;
847 }
848 entry.reports.push(report);
849 }
850 self.subscribers.push(Subscriber {
851 id,
852 removed: Vec::new(),
853 });
854 id
855 }
856
857 pub fn unsubscribe(&mut self, id: SubscriberId) -> Result<()> {
864 self.drop_field_unit();
865 if id == SubscriberId::DEFAULT {
866 return Err(SceneError::InvalidInput(
867 "the default subscriber cannot be removed",
868 ));
869 }
870 let i = self.subscriber_index(id)?;
871 self.subscribers.remove(i);
872 for (_, entry) in self.entries.iter_mut() {
873 entry.reports.remove(i);
874 }
875 Ok(())
876 }
877
878 pub fn take_changes_for(&mut self, id: SubscriberId) -> Result<Vec<MeshChanges>> {
885 self.drop_field_unit();
886 let i = self.subscriber_index(id)?;
887 Ok(self.take_at(i))
888 }
889
890 fn subscriber_index(&self, id: SubscriberId) -> Result<usize> {
891 self.subscribers
892 .binary_search_by_key(&id, |s| s.id)
893 .map_err(|_| SceneError::InvalidInput("unknown or removed subscriber"))
894 }
895
896 fn take_at(&mut self, i: usize) -> Vec<MeshChanges> {
898 let mut out = std::mem::take(&mut self.subscribers[i].removed);
899 for (id, entry) in self.entries.iter_mut() {
900 let r = &mut entry.reports[i];
901 if r.is_clean() {
902 *r = Report::clean();
903 } else {
904 out.push(r.take(id, false));
905 }
906 }
907 out.sort_by_key(|c| c.id);
908 out
909 }
910
911 pub fn add_channel(&mut self, id: MeshId, desc: ChannelDesc) -> Result<()> {
921 self.drop_field_unit();
922 check_name(&desc.name)?;
923 let entry = self.entry_mut(id)?;
924 let name = desc.name.clone();
925 entry.mesh.add_channel(desc)?;
926 entry.report_channel(&name);
927 Ok(())
928 }
929
930 pub fn capture_rest_sizes(&mut self, id: MeshId, only_if_missing: bool) -> Result<()> {
940 self.drop_field_unit();
941 let entry = self.entry_mut(id)?;
942 if only_if_missing {
943 fast_mesh_ops::stretch::ensure_rest_sizes(&mut entry.mesh)?;
944 } else {
945 fast_mesh_ops::stretch::capture_rest_sizes(&mut entry.mesh)?;
946 }
947 Ok(())
948 }
949
950 pub fn ensure_incidence(&mut self, id: MeshId) -> Result<()> {
956 self.entry_mut(id)?.mesh.ensure_incidence()?;
957 Ok(())
958 }
959
960 pub fn remove_channel(&mut self, id: MeshId, name: &str) -> Result<ChannelDesc> {
971 self.drop_field_unit();
972 check_name(name)?;
973 let entry = self.entry_mut(id)?;
974 let desc = entry.mesh.remove_channel(name)?;
975 entry.report_channel(name);
976 Ok(desc)
977 }
978
979 pub fn derived_channel_mut(&mut self, id: MeshId, name: &str) -> Result<&mut [f32]> {
989 self.drop_field_unit();
990 check_name(name)?;
991 let entry = self.entry_mut(id)?;
992 entry.mesh.derived_channel_mut(name)?;
994 entry.report_channel(name);
995 Ok(entry.mesh.derived_channel_mut(name)?)
996 }
997
998 pub fn compact(&mut self, id: MeshId) -> Result<Remap> {
1018 self.drop_field_unit();
1019 let entry = self.entries.get_mut(id).ok_or(SceneError::UnknownMesh)?;
1020 let remap = entry.mesh.compact()?;
1021 self.history.forget(id, None);
1023 entry.pending = Some(ChangeSet::default());
1026 entry.report_everything();
1027 let _ = entry.update_bvh();
1028 let _ = entry.update_normals();
1030 entry.recolor_all();
1033 for f in self.fields.iter_mut().filter(|f| f.desc.on == id) {
1034 let old = std::mem::take(&mut f.nearest);
1035 let mut nearest = Vec::new();
1036 if nearest.try_reserve_exact(entry.mesh.vertex_slots()).is_ok() {
1039 nearest.resize(entry.mesh.vertex_slots(), u32::MAX);
1040 for (v, n) in old.into_iter().enumerate() {
1041 if let Some(w) = remap.vertex(v as VertexId) {
1042 nearest[w as usize] = n;
1043 }
1044 }
1045 }
1046 f.nearest = nearest;
1047 }
1048 self.run_eager(Some(&[id]));
1049 Ok(remap)
1050 }
1051
1052 pub(crate) fn entry(&self, id: MeshId) -> Result<&Entry> {
1053 self.entries.get(id).ok_or(SceneError::UnknownMesh)
1054 }
1055
1056 pub fn mesh(&self, id: MeshId) -> Result<&Mesh> {
1061 Ok(&self.entry(id)?.mesh)
1062 }
1063
1064 pub fn ids(&self) -> impl Iterator<Item = MeshId> {
1066 self.entries.iter().map(|(id, _)| id)
1067 }
1068
1069 pub fn mesh_id(&self, index: u32, generation: u32) -> Option<MeshId> {
1074 self.entries.live_id(index, generation)
1075 }
1076
1077 pub fn placement(&self, id: MeshId) -> Result<Placement> {
1082 Ok(self.entry(id)?.placement)
1083 }
1084
1085 pub fn set_placement(&mut self, id: MeshId, placement: Placement) -> Result<()> {
1104 self.drop_field_unit();
1105 placement.validate()?;
1106 let entry = self.entries.get_mut(id).ok_or(SceneError::UnknownMesh)?;
1107 let old = entry.placement;
1108 if old == placement {
1109 return Ok(());
1110 }
1111 self.history.reserve()?;
1112 entry.placement = placement;
1113 entry.report_placement();
1114 self.history
1115 .record_placement(&mut self.entries, id, old, placement);
1116 self.run_eager(Some(&[id]));
1117 Ok(())
1118 }
1119
1120 pub fn is_current(&self, id: MeshId) -> Result<bool> {
1125 Ok(self.entry(id)?.is_current())
1126 }
1127
1128 pub fn bounds(&self, id: MeshId) -> Result<Option<Aabb>> {
1136 let mesh = self.mesh(id)?;
1137 let positions = mesh.positions();
1138 let mut out = Aabb::EMPTY;
1139 for t in 0..mesh.triangle_slots() as u32 {
1140 if let Some(tri) = mesh.triangle(t) {
1143 out.grow(&Aabb::of_triangle(positions, tri));
1144 }
1145 }
1146 if out.is_empty() {
1147 Ok(None)
1148 } else {
1149 Ok(Some(out))
1150 }
1151 }
1152
1153 pub(crate) fn prepare(&mut self, only: Option<&[MeshId]>) -> Result<()> {
1164 let wanted = |id: MeshId| only.is_none_or(|ids| ids.contains(&id));
1165 let mut stale = None;
1166 for (id, entry) in self.entries.iter_mut() {
1167 if !wanted(id) {
1168 continue;
1169 }
1170 if entry.mode != UpdateMode::Manual {
1171 entry.update_bvh()?;
1172 } else if stale.is_none() && !entry.is_current() {
1173 stale = Some(id);
1174 }
1175 }
1176 match stale {
1177 Some(id) => Err(SceneError::StaleBvh(id)),
1178 None => Ok(()),
1179 }
1180 }
1181}
1182
1183pub(crate) const FIELD_PREFIX: &str = "field:";
1185
1186fn check_name(name: &str) -> Result<()> {
1188 if name.starts_with(FIELD_PREFIX) {
1189 return Err(SceneError::InvalidInput(
1190 "channel names starting with `field:` are reserved",
1191 ));
1192 }
1193 Ok(())
1194}
1195
1196#[cfg(test)]
1199pub(crate) mod fault {
1200 use std::cell::Cell;
1201
1202 use fast_mesh_bvh::BvhError;
1203 use fast_mesh_store::StoreError;
1204
1205 thread_local! {
1206 static BVH_UPDATE: Cell<Option<u32>> = const { Cell::new(None) };
1208 }
1209
1210 pub(crate) fn fail_bvh_update_on(n: u32) {
1213 assert!(n > 0);
1214 BVH_UPDATE.with(|c| c.set(Some(n - 1)));
1215 }
1216
1217 thread_local! {
1218 static PATCH_CALLS: Cell<u32> = const { Cell::new(0) };
1220 static PATCH_FAILS: Cell<u64> = const { Cell::new(0) };
1222 }
1223
1224 pub(crate) fn fail_patch_on(n: u32) {
1229 let at = PATCH_CALLS.with(Cell::get) + n;
1230 assert!(n > 0 && at < 64);
1231 PATCH_FAILS.with(|f| f.set(f.get() | 1 << at));
1232 }
1233
1234 pub(crate) fn before_patch() -> Result<(), StoreError> {
1236 let fails = PATCH_FAILS.with(Cell::get);
1237 if fails == 0 {
1238 return Ok(());
1239 }
1240 let call = PATCH_CALLS.with(|c| {
1241 c.set(c.get() + 1);
1242 c.get()
1243 });
1244 if fails & 1 << call == 0 {
1245 return Ok(());
1246 }
1247 let left = fails & !(1 << call);
1248 PATCH_FAILS.with(|f| f.set(left));
1249 if left == 0 {
1250 PATCH_CALLS.with(|c| c.set(0));
1251 }
1252 Err(StoreError::OutOfMemory)
1253 }
1254
1255 thread_local! {
1256 static REBUILDS: Cell<u32> = const { Cell::new(0) };
1258 }
1259
1260 pub(crate) fn count_rebuild() {
1262 REBUILDS.with(|c| c.set(c.get() + 1));
1263 }
1264
1265 pub(crate) fn take_rebuilds() -> u32 {
1267 REBUILDS.with(|c| c.replace(0))
1268 }
1269
1270 pub(crate) fn before_bvh_update() -> Result<(), BvhError> {
1272 BVH_UPDATE.with(|c| match c.get() {
1273 Some(0) => {
1274 c.set(None);
1275 Err(BvhError::OutOfMemory)
1276 }
1277 Some(n) => {
1278 c.set(Some(n - 1));
1279 Ok(())
1280 }
1281 None => Ok(()),
1282 })
1283 }
1284
1285 thread_local! {
1286 static RESERVE: Cell<Option<u32>> = const { Cell::new(None) };
1288 }
1289
1290 pub(crate) fn fail_reserve_on(n: u32) {
1293 assert!(n > 0);
1294 RESERVE.with(|c| c.set(Some(n - 1)));
1295 }
1296
1297 pub(crate) fn before_reserve() -> Result<(), StoreError> {
1299 RESERVE.with(|c| match c.get() {
1300 Some(0) => {
1301 c.set(None);
1302 Err(StoreError::OutOfMemory)
1303 }
1304 Some(n) => {
1305 c.set(Some(n - 1));
1306 Ok(())
1307 }
1308 None => Ok(()),
1309 })
1310 }
1311
1312 thread_local! {
1313 static CONTACT: Cell<Option<u32>> = const { Cell::new(None) };
1315 }
1316
1317 pub(crate) fn fail_contact_on(n: u32) {
1320 assert!(n > 0);
1321 CONTACT.with(|c| c.set(Some(n - 1)));
1322 }
1323
1324 pub(crate) fn before_contact() -> Result<(), StoreError> {
1326 CONTACT.with(|c| match c.get() {
1327 Some(0) => {
1328 c.set(None);
1329 Err(StoreError::OutOfMemory)
1330 }
1331 Some(n) => {
1332 c.set(Some(n - 1));
1333 Ok(())
1334 }
1335 None => Ok(()),
1336 })
1337 }
1338}
1339
1340#[cfg(test)]
1341mod tests {
1342 use super::*;
1343
1344 fn tri() -> Mesh {
1345 Mesh::from_buffers(&[0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0], &[0, 1, 2]).unwrap()
1346 }
1347
1348 #[test]
1349 fn stale_ids_are_rejected() {
1350 let mut scene = Scene::new(SceneOptions::default());
1351 let a = scene.add_mesh(tri(), MeshOptions::default()).unwrap();
1352 assert!(scene.mesh(a).is_ok());
1353 assert!(scene.remove_mesh(a).is_ok());
1354 assert_eq!(scene.mesh(a).err(), Some(SceneError::UnknownMesh));
1355 assert_eq!(scene.placement(a).err(), Some(SceneError::UnknownMesh));
1356 assert_eq!(
1357 scene.set_placement(a, Placement::IDENTITY),
1358 Err(SceneError::UnknownMesh)
1359 );
1360 assert_eq!(scene.is_current(a).err(), Some(SceneError::UnknownMesh));
1361 assert_eq!(scene.remove_mesh(a).err(), Some(SceneError::UnknownMesh));
1362 let b = scene.add_mesh(tri(), MeshOptions::default()).unwrap();
1364 assert_ne!(a, b);
1365 assert_eq!(scene.mesh(a).err(), Some(SceneError::UnknownMesh));
1366 assert!(scene.mesh(b).is_ok());
1367 }
1368
1369 #[test]
1370 fn mesh_id_from_parts_only_for_live_meshes() {
1371 let mut scene = Scene::new(SceneOptions::default());
1372 let a = scene.add_mesh(tri(), MeshOptions::default()).unwrap();
1373 assert_eq!(scene.mesh_id(a.index(), a.generation()), Some(a));
1374 assert_eq!(scene.mesh_id(a.index(), a.generation() + 1), None);
1375 assert_eq!(scene.mesh_id(a.index() + 1, 0), None);
1376 scene.remove_mesh(a).unwrap();
1377 assert_eq!(scene.mesh_id(a.index(), a.generation()), None);
1378 let b = scene.add_mesh(tri(), MeshOptions::default()).unwrap();
1380 assert_eq!(b.index(), a.index());
1381 assert_eq!(scene.mesh_id(b.index(), b.generation()), Some(b));
1382 assert_eq!(scene.mesh_id(a.index(), a.generation()), None);
1383 }
1384
1385 #[test]
1386 fn ids_iterate_in_index_order() {
1387 let mut scene = Scene::new(SceneOptions::default());
1388 let ids: Vec<_> = (0..4)
1389 .map(|_| scene.add_mesh(tri(), MeshOptions::default()).unwrap())
1390 .collect();
1391 scene.remove_mesh(ids[1]).unwrap();
1392 assert_eq!(scene.ids().collect::<Vec<_>>(), [ids[0], ids[2], ids[3]]);
1393 let again = scene.add_mesh(tri(), MeshOptions::default()).unwrap();
1394 assert_eq!(
1396 scene.ids().collect::<Vec<_>>(),
1397 [ids[0], again, ids[2], ids[3]]
1398 );
1399 }
1400
1401 #[test]
1402 fn placement_round_trip_and_validation() {
1403 let mut scene = Scene::new(SceneOptions::default());
1404 let bad = Placement {
1405 translation: [f64::NAN, 0.0, 0.0],
1406 ..Placement::IDENTITY
1407 };
1408 let opts = MeshOptions {
1409 placement: bad,
1410 ..MeshOptions::default()
1411 };
1412 assert!(matches!(
1413 scene.add_mesh(tri(), opts),
1414 Err(SceneError::InvalidInput(_))
1415 ));
1416 assert_eq!(scene.ids().count(), 0);
1417 let id = scene.add_mesh(tri(), MeshOptions::default()).unwrap();
1418 let moved = Placement {
1419 translation: [1.0, 2.0, 3.0],
1420 ..Placement::IDENTITY
1421 };
1422 scene.set_placement(id, moved).unwrap();
1423 assert_eq!(scene.placement(id), Ok(moved));
1424 assert!(scene.set_placement(id, bad).is_err());
1425 assert_eq!(scene.placement(id), Ok(moved));
1426 assert_eq!(scene.is_current(id), Ok(true));
1427 }
1428
1429 #[test]
1430 fn scaled_placement_undoes_and_rejects_bad_scales() {
1431 let mut scene = Scene::new(SceneOptions::default());
1432 let id = scene.add_mesh(tri(), MeshOptions::default()).unwrap();
1433 scene.take_changes();
1434 let scaled = Placement {
1435 translation: [1.0, 2.0, 3.0],
1436 scale: [2.0, 0.5, 1.0],
1437 ..Placement::IDENTITY
1438 };
1439 scene.set_placement(id, scaled).unwrap();
1440 assert_eq!(scene.placement(id), Ok(scaled));
1441 assert!(scene.take_changes()[0].placement_changed);
1442 assert_eq!(scene.undo(), Ok(true));
1444 assert_eq!(scene.placement(id), Ok(Placement::IDENTITY));
1445 assert_eq!(scene.redo(), Ok(true));
1446 assert_eq!(scene.placement(id), Ok(scaled));
1447 scene.begin_step();
1449 scene
1450 .set_placement(
1451 id,
1452 Placement {
1453 scale: [3.0, 0.5, 1.0],
1454 ..scaled
1455 },
1456 )
1457 .unwrap();
1458 scene
1459 .set_placement(
1460 id,
1461 Placement {
1462 scale: [4.0, 0.5, 1.0],
1463 ..scaled
1464 },
1465 )
1466 .unwrap();
1467 scene.end_step().unwrap();
1468 assert_eq!(scene.undo(), Ok(true));
1469 assert_eq!(scene.placement(id), Ok(scaled));
1470 for scale in [
1472 [0.0, 1.0, 1.0],
1473 [1.0, -1.0, 1.0],
1474 [f64::NAN, 1.0, 1.0],
1475 [1.0, f64::INFINITY, 1.0],
1476 ] {
1477 let bad = Placement {
1478 scale,
1479 ..Placement::IDENTITY
1480 };
1481 assert!(
1482 matches!(
1483 scene.set_placement(id, bad),
1484 Err(SceneError::InvalidInput(_))
1485 ),
1486 "scale {scale:?}"
1487 );
1488 assert_eq!(scene.placement(id), Ok(scaled));
1489 }
1490 }
1491
1492 #[test]
1493 fn mode_getter_follows_set_mode() {
1494 let mut scene = Scene::new(SceneOptions::default());
1495 let id = scene.add_mesh(tri(), MeshOptions::default()).unwrap();
1496 assert_eq!(scene.mode(id), Ok(UpdateMode::Eager));
1497 scene.set_mode(id, UpdateMode::Lazy).unwrap();
1498 assert_eq!(scene.mode(id), Ok(UpdateMode::Lazy));
1499 scene.set_mode(id, UpdateMode::Manual).unwrap();
1500 assert_eq!(scene.mode(id), Ok(UpdateMode::Manual));
1501 scene.remove_mesh(id).unwrap();
1502 assert_eq!(scene.mode(id).err(), Some(SceneError::UnknownMesh));
1503 }
1504
1505 #[test]
1506 fn bounds_cover_live_triangles_only() {
1507 let mut scene = Scene::new(SceneOptions::default());
1508 let id = scene.add_mesh(tri(), MeshOptions::default()).unwrap();
1509 let b = scene.bounds(id).unwrap().unwrap();
1510 assert_eq!(b.min, [0.0, 0.0, 0.0]);
1511 assert_eq!(b.max, [1.0, 1.0, 0.0]);
1512 scene
1514 .edit(id, |tx| tx.add_vertices(&[[50.0, 50.0, 50.0]]))
1515 .unwrap();
1516 let b = scene.bounds(id).unwrap().unwrap();
1517 assert_eq!((b.min, b.max), ([0.0, 0.0, 0.0], [1.0, 1.0, 0.0]));
1518 scene.edit(id, |tx| tx.remove_triangles(&[0])).unwrap();
1520 assert_eq!(scene.bounds(id), Ok(None));
1521 scene.remove_mesh(id).unwrap();
1522 assert_eq!(scene.bounds(id).err(), Some(SceneError::UnknownMesh));
1523 }
1524
1525 #[test]
1526 fn lazy_and_manual_adds_defer_the_bvh_build() {
1527 let mut scene = Scene::new(SceneOptions::default());
1528 let deferred = |mode| MeshOptions {
1529 mode,
1530 defer_bvh: true,
1531 ..MeshOptions::default()
1532 };
1533 let eager = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
1535 assert_eq!(scene.is_current(eager), Ok(true));
1536 let eager_flagged = scene
1537 .add_mesh(grid(2), deferred(UpdateMode::Eager))
1538 .unwrap();
1539 assert_eq!(scene.is_current(eager_flagged), Ok(true));
1540 let lazy = scene.add_mesh(grid(4), deferred(UpdateMode::Lazy)).unwrap();
1541 assert_eq!(scene.mode(lazy), Ok(UpdateMode::Lazy));
1543 assert_eq!(scene.is_current(lazy), Ok(false));
1544 assert_eq!(scene.bvh(lazy).err(), Some(SceneError::StaleBvh(lazy)));
1545 let hit = scene
1547 .raycast(
1548 [2.0, 2.0, 10.0],
1549 [0.0, 0.0, -1.0],
1550 &crate::SceneRayOptions::default(),
1551 )
1552 .unwrap();
1553 assert!(hit.is_some());
1554 assert_eq!(scene.is_current(lazy), Ok(true));
1555 assert!(scene.bvh(lazy).is_ok());
1556 let manual = scene
1558 .add_mesh(grid(4), deferred(UpdateMode::Manual))
1559 .unwrap();
1560 assert_eq!(scene.is_current(manual), Ok(false));
1561 scene.update(manual).unwrap();
1562 assert_eq!(scene.is_current(manual), Ok(true));
1563 let manual2 = scene
1564 .add_mesh(grid(2), deferred(UpdateMode::Manual))
1565 .unwrap();
1566 scene.set_mode(manual2, UpdateMode::Eager).unwrap();
1567 assert_eq!(scene.is_current(manual2), Ok(true));
1568 assert_valid(&scene, lazy);
1569 assert_valid(&scene, manual);
1570 assert_valid(&scene, manual2);
1571 }
1572
1573 fn grid(n: u32) -> Mesh {
1575 let mut pos = Vec::new();
1576 for y in 0..=n {
1577 for x in 0..=n {
1578 pos.extend_from_slice(&[x as f32, y as f32, 0.0]);
1579 }
1580 }
1581 let mut idx = Vec::new();
1582 for y in 0..n {
1583 for x in 0..n {
1584 let a = y * (n + 1) + x;
1585 let b = a + 1;
1586 let c = a + n + 1;
1587 idx.extend_from_slice(&[a, b, c, b, c + 1, c]);
1588 }
1589 }
1590 Mesh::from_buffers(&pos, &idx).unwrap()
1591 }
1592
1593 fn with_mode(mode: UpdateMode) -> MeshOptions {
1594 MeshOptions {
1595 mode,
1596 ..MeshOptions::default()
1597 }
1598 }
1599
1600 fn lift(scene: &mut Scene, id: MeshId, v: u32, z: f32) {
1601 scene
1602 .edit(id, |tx| {
1603 let p = tx.mesh().position(v).unwrap();
1604 tx.set_positions(&[v], &[[p[0], p[1], z]])
1605 })
1606 .unwrap();
1607 }
1608
1609 fn assert_valid(scene: &Scene, id: MeshId) {
1610 let e = scene.entries.get(id).unwrap();
1611 e.bvh.validate(&e.mesh).unwrap();
1612 }
1613
1614 #[test]
1615 fn eager_bvh_stays_current() {
1616 let mut scene = Scene::new(SceneOptions::default());
1617 let id = scene.add_mesh(grid(4), MeshOptions::default()).unwrap();
1618 let r = scene
1619 .edit(id, |tx| {
1620 tx.set_positions(&[6], &[[1.0, 1.0, 2.0]]).map(|()| 7)
1621 })
1622 .unwrap();
1623 assert_eq!(r, 7);
1624 assert_eq!(scene.is_current(id), Ok(true));
1625 assert_valid(&scene, id);
1626 assert!(scene.entries.get(id).unwrap().pending.is_none());
1627 assert_eq!(scene.history.undo_len(), 1);
1628 }
1629
1630 #[test]
1631 fn failed_edit_changes_nothing() {
1632 let mut scene = Scene::new(SceneOptions::default());
1633 let id = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
1634 scene.take_changes();
1635 let before = scene.mesh(id).unwrap().revision();
1636 let err = scene.edit(id, |tx| {
1637 tx.set_positions(&[0], &[[5.0, 5.0, 5.0]])?;
1638 tx.remove_vertices(&[1])
1639 });
1640 assert!(matches!(err, Err(SceneError::Store(_))));
1641 assert_eq!(scene.mesh(id).unwrap().revision(), before);
1642 assert_eq!(scene.mesh(id).unwrap().position(0), Some([0.0, 0.0, 0.0]));
1643 assert_eq!(scene.history.undo_len(), 0);
1644 assert!(scene.take_changes().is_empty());
1645 assert_eq!(scene.is_current(id), Ok(true));
1646 scene.remove_mesh(id).unwrap();
1647 assert_eq!(
1648 scene.edit(id, |_| Ok::<(), StoreError>(())).err(),
1649 Some(SceneError::UnknownMesh)
1650 );
1651 }
1652
1653 #[test]
1654 fn lazy_waits_for_flush() {
1655 let mut scene = Scene::new(SceneOptions::default());
1656 let id = scene
1657 .add_mesh(grid(4), with_mode(UpdateMode::Lazy))
1658 .unwrap();
1659 lift(&mut scene, id, 6, 1.0);
1660 assert_eq!(scene.is_current(id), Ok(false));
1661 scene.flush().unwrap();
1662 assert_eq!(scene.is_current(id), Ok(true));
1663 assert_valid(&scene, id);
1664 }
1665
1666 #[test]
1667 fn manual_waits_for_update() {
1668 let mut scene = Scene::new(SceneOptions::default());
1669 let id = scene
1670 .add_mesh(grid(4), with_mode(UpdateMode::Manual))
1671 .unwrap();
1672 lift(&mut scene, id, 6, 1.0);
1673 assert_eq!(scene.is_current(id), Ok(false));
1674 scene.flush().unwrap();
1675 assert_eq!(scene.is_current(id), Ok(false));
1676 scene.update(id).unwrap();
1677 assert_eq!(scene.is_current(id), Ok(true));
1678 assert_valid(&scene, id);
1679 lift(&mut scene, id, 7, 1.0);
1681 assert_eq!(scene.is_current(id), Ok(false));
1682 scene.set_mode(id, UpdateMode::Eager).unwrap();
1683 assert_eq!(scene.is_current(id), Ok(true));
1684 scene.remove_mesh(id).unwrap();
1685 assert_eq!(
1686 scene.set_mode(id, UpdateMode::Lazy),
1687 Err(SceneError::UnknownMesh)
1688 );
1689 assert_eq!(scene.update(id), Err(SceneError::UnknownMesh));
1690 }
1691
1692 #[test]
1693 fn pending_changes_merge_across_commits() {
1694 let mut scene = Scene::new(SceneOptions::default());
1695 let id = scene
1696 .add_mesh(grid(6), with_mode(UpdateMode::Lazy))
1697 .unwrap();
1698 lift(&mut scene, id, 8, 1.5);
1699 scene
1700 .edit(id, |tx| tx.remove_triangles(&[0, 1, 5]))
1701 .unwrap();
1702 let added = scene
1703 .edit(id, |tx| {
1704 let v = tx.add_vertices(&[[3.5, 3.5, 2.0]])?;
1705 tx.add_triangles(&[[v[0], 10, 11], [v[0], 11, 18]])
1706 })
1707 .unwrap();
1708 lift(&mut scene, id, 8, -0.5);
1709 scene
1710 .edit(id, |tx| {
1711 tx.remove_triangles(&[added[1]])?;
1712 tx.set_triangles(&[7], &[[0, 1, 2]])
1713 })
1714 .unwrap();
1715 assert_eq!(scene.history.undo_len(), 5);
1716 assert_eq!(scene.is_current(id), Ok(false));
1717 scene.flush().unwrap();
1718 assert_eq!(scene.is_current(id), Ok(true));
1719 assert_valid(&scene, id);
1720 let e = scene.entries.get(id).unwrap();
1721 let fresh = Bvh::build(&e.mesh, &BuildOptions::default()).unwrap();
1722 for (lo, hi) in [
1723 ([-1.0, -1.0, -1.0], [7.0, 7.0, 3.0]),
1724 ([0.5, 0.5, -1.0], [2.5, 2.5, 3.0]),
1725 ([2.0, 2.0, 0.5], [4.0, 4.0, 2.5]),
1726 ([3.0, 0.0, -1.0], [3.2, 6.0, 0.0]),
1727 ] {
1728 let (mut a, mut b) = (Vec::new(), Vec::new());
1729 e.bvh.query_aabb(&e.mesh, lo, hi, &mut a);
1730 fresh.query_aabb(&e.mesh, lo, hi, &mut b);
1731 a.sort_unstable();
1732 b.sort_unstable();
1733 assert!(!b.is_empty());
1734 assert_eq!(a, b);
1735 }
1736 }
1737
1738 #[test]
1739 fn eager_update_failure_leaves_bvh_pending() {
1740 let mut scene = Scene::new(SceneOptions::default());
1741 let id = scene.add_mesh(grid(4), MeshOptions::default()).unwrap();
1742 fault::fail_bvh_update_on(1);
1743 lift(&mut scene, id, 6, 1.0);
1744 assert_eq!(scene.mesh(id).unwrap().position(6), Some([1.0, 1.0, 1.0]));
1745 assert_eq!(scene.history.undo_len(), 1);
1746 assert_eq!(scene.is_current(id), Ok(false));
1747 assert!(scene.entries.get(id).unwrap().pending.is_some());
1748 fault::fail_bvh_update_on(1);
1750 lift(&mut scene, id, 12, 1.0);
1751 assert_eq!(scene.is_current(id), Ok(false));
1752 scene.update(id).unwrap();
1753 assert_eq!(scene.is_current(id), Ok(true));
1754 assert!(scene.entries.get(id).unwrap().pending.is_none());
1755 assert_valid(&scene, id);
1756 fault::fail_bvh_update_on(1);
1758 lift(&mut scene, id, 7, 1.0);
1759 fault::fail_bvh_update_on(1);
1760 assert_eq!(
1761 scene.update(id),
1762 Err(SceneError::Bvh(fast_mesh_bvh::BvhError::OutOfMemory))
1763 );
1764 assert_eq!(scene.is_current(id), Ok(false));
1765 scene.flush().unwrap();
1767 assert_eq!(scene.is_current(id), Ok(true));
1768 assert_valid(&scene, id);
1769 }
1770
1771 #[test]
1772 fn take_changes_reports_and_resets() {
1773 let mut scene = Scene::new(SceneOptions::default());
1774 let a = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
1775 let b = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
1776 let first = scene.take_changes();
1777 assert_eq!(first.len(), 2);
1778 assert_eq!(first[0].id, a);
1779 assert_eq!(first[1].id, b);
1780 assert!(first.iter().all(|c| c.added && c.changes.is_none()));
1781 assert!(scene.take_changes().is_empty());
1782
1783 lift(&mut scene, b, 4, 1.0);
1784 lift(&mut scene, b, 1, 1.0);
1785 let moved = Placement {
1786 translation: [1.0, 0.0, 0.0],
1787 ..Placement::IDENTITY
1788 };
1789 scene.set_placement(a, moved).unwrap();
1790 scene.set_placement(a, Placement::IDENTITY).unwrap();
1791 let ch = scene.take_changes();
1792 assert_eq!(ch.len(), 2);
1793 assert_eq!(ch[0].id, a);
1794 assert!(ch[0].placement_changed && !ch[0].added && !ch[0].removed);
1795 assert_eq!(ch[0].changes.as_ref().map(ChangeSet::is_empty), Some(true));
1796 assert_eq!(ch[1].id, b);
1797 assert!(!ch[1].placement_changed);
1798 assert_eq!(ch[1].changes.as_ref().unwrap().vertices_moved, [1, 4]);
1799 assert!(scene.take_changes().is_empty());
1800
1801 let recorded = scene.history.undo_len();
1803 scene.edit(a, |_| Ok::<(), StoreError>(())).unwrap();
1804 assert_eq!(scene.history.undo_len(), recorded);
1805 assert!(scene.take_changes().is_empty());
1806
1807 lift(&mut scene, a, 0, 1.0);
1809 scene.remove_mesh(a).unwrap();
1810 let ch = scene.take_changes();
1811 assert_eq!(ch.len(), 1);
1812 assert_eq!(ch[0].id, a);
1813 assert!(ch[0].removed && !ch[0].added);
1814 assert_eq!(ch[0].changes.as_ref().unwrap().vertices_moved, [0]);
1815 assert!(scene.take_changes().is_empty());
1816 }
1817
1818 #[test]
1819 fn added_then_removed_is_not_reported() {
1820 let mut scene = Scene::new(SceneOptions::default());
1821 let keep = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
1822 scene.take_changes();
1823 let gone = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
1824 lift(&mut scene, gone, 0, 1.0);
1825 scene.remove_mesh(gone).unwrap();
1826 assert!(scene.take_changes().is_empty());
1827
1828 let v = scene
1830 .edit(keep, |tx| tx.add_vertices(&[[9.0, 9.0, 9.0]]))
1831 .unwrap();
1832 scene.edit(keep, |tx| tx.remove_vertices(&v)).unwrap();
1833 let ch = scene.take_changes();
1834 assert!(ch.is_empty(), "{ch:?}");
1835 }
1836
1837 #[test]
1838 fn compact_reports_everything() {
1839 let mut scene = Scene::new(SceneOptions::default());
1840 let id = scene.add_mesh(grid(3), MeshOptions::default()).unwrap();
1841 scene.take_changes();
1842 scene.edit(id, |tx| tx.remove_triangles(&[0])).unwrap();
1843 scene.edit(id, |tx| tx.remove_vertices(&[0])).unwrap();
1844 let remap = scene.compact(id).unwrap();
1845 assert_eq!(remap.vertex(0), None);
1846 assert_eq!(remap.vertex(1), Some(0));
1847 assert_eq!(remap.triangle(0), None);
1848 assert_eq!(remap.triangle(1), Some(0));
1849 assert_eq!(scene.mesh(id).unwrap().vertex_slots(), 15);
1850 assert_eq!(scene.is_current(id), Ok(true));
1851 assert_valid(&scene, id);
1852 let ch = scene.take_changes();
1853 assert_eq!(ch.len(), 1);
1854 assert!(ch[0].changes.is_none() && !ch[0].added);
1855 assert!(scene.take_changes().is_empty());
1856 let m = scene
1858 .add_mesh(grid(2), with_mode(UpdateMode::Manual))
1859 .unwrap();
1860 scene.edit(m, |tx| tx.remove_triangles(&[3])).unwrap();
1861 scene.compact(m).unwrap();
1862 assert_eq!(scene.is_current(m), Ok(true));
1863 assert_valid(&scene, m);
1864 }
1865
1866 #[test]
1867 fn channel_wrappers() {
1868 let mut scene = Scene::new(SceneOptions::default());
1869 let id = scene.add_mesh(grid(1), MeshOptions::default()).unwrap();
1870 scene
1871 .add_channel(id, ChannelDesc::derived("curv", 1))
1872 .unwrap();
1873 scene.derived_channel_mut(id, "curv").unwrap()[2] = 4.0;
1874 assert_eq!(scene.mesh(id).unwrap().channel("curv").unwrap()[2], 4.0);
1875 assert!(matches!(
1876 scene.add_channel(id, ChannelDesc::derived("curv", 1)),
1877 Err(SceneError::Store(_))
1878 ));
1879 assert_eq!(scene.remove_channel(id, "curv").unwrap().name, "curv");
1880 assert!(scene.derived_channel_mut(id, "curv").is_err());
1881 assert_eq!(scene.is_current(id), Ok(true));
1882 }
1883
1884 fn z(scene: &Scene, id: MeshId, v: u32) -> f32 {
1885 scene.mesh(id).unwrap().position(v).unwrap()[2]
1886 }
1887
1888 fn moved(x: f64) -> Placement {
1889 Placement {
1890 translation: [x, 0.0, 0.0],
1891 ..Placement::IDENTITY
1892 }
1893 }
1894
1895 #[test]
1896 fn step_groups_edits_across_meshes() {
1897 let mut scene = Scene::new(SceneOptions::default());
1898 let a = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
1899 let b = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
1900 assert!(!scene.can_undo() && !scene.can_redo());
1901 scene.begin_step();
1902 lift(&mut scene, a, 0, 1.0);
1903 lift(&mut scene, b, 1, 2.0);
1904 scene.set_placement(a, moved(3.0)).unwrap();
1905 lift(&mut scene, a, 0, 4.0);
1906 assert!(scene.can_undo());
1907 scene.end_step().unwrap();
1908 assert_eq!(scene.history.undo_len(), 1);
1909 scene.take_changes();
1910
1911 assert_eq!(scene.undo(), Ok(true));
1912 assert_eq!((z(&scene, a, 0), z(&scene, b, 1)), (0.0, 0.0));
1913 assert_eq!(scene.placement(a), Ok(Placement::IDENTITY));
1914 assert!(!scene.can_undo() && scene.can_redo());
1915 let ch = scene.take_changes();
1916 assert_eq!(ch.len(), 2);
1917 assert!(ch[0].placement_changed);
1918 assert_eq!(ch[0].changes.as_ref().unwrap().vertices_moved, [0]);
1919 assert_eq!(ch[1].changes.as_ref().unwrap().vertices_moved, [1]);
1920 assert_eq!(scene.undo(), Ok(false));
1921
1922 assert_eq!(scene.redo(), Ok(true));
1923 assert_eq!((z(&scene, a, 0), z(&scene, b, 1)), (4.0, 2.0));
1924 assert_eq!(scene.placement(a), Ok(moved(3.0)));
1925 assert!(scene.can_undo() && !scene.can_redo());
1926 assert_eq!(scene.redo(), Ok(false));
1927 assert_valid(&scene, a);
1928 assert_valid(&scene, b);
1929 }
1930
1931 #[test]
1932 fn implicit_steps_per_operation() {
1933 let mut scene = Scene::new(SceneOptions::default());
1934 let a = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
1935 let b = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
1936 lift(&mut scene, a, 0, 1.0);
1937 lift(&mut scene, b, 0, 1.0);
1938 scene.set_placement(a, moved(1.0)).unwrap();
1939 scene.edit(a, |_| Ok::<(), StoreError>(())).unwrap();
1941 scene.set_placement(a, moved(1.0)).unwrap();
1942 scene.begin_step();
1943 scene.end_step().unwrap();
1944 assert_eq!(scene.history.undo_len(), 3);
1945 scene.take_changes();
1946
1947 assert_eq!(scene.undo(), Ok(true));
1948 assert_eq!(scene.placement(a), Ok(Placement::IDENTITY));
1949 assert_eq!((z(&scene, a, 0), z(&scene, b, 0)), (1.0, 1.0));
1950 let ch = scene.take_changes();
1951 assert_eq!(ch.len(), 1);
1952 assert!(ch[0].placement_changed);
1953 assert_eq!(ch[0].changes.as_ref().map(ChangeSet::is_empty), Some(true));
1954 assert_eq!(scene.undo(), Ok(true));
1955 assert_eq!((z(&scene, a, 0), z(&scene, b, 0)), (1.0, 0.0));
1956 assert_eq!(scene.undo(), Ok(true));
1957 assert_eq!(z(&scene, a, 0), 0.0);
1958 assert_eq!(scene.undo(), Ok(false));
1959
1960 scene.begin_step();
1962 scene.begin_step();
1963 lift(&mut scene, a, 1, 1.0);
1964 scene.end_step().unwrap();
1965 lift(&mut scene, b, 1, 1.0);
1966 scene.end_step().unwrap();
1967 assert_eq!(scene.end_step(), Err(SceneError::StepNotOpen));
1968 assert_eq!(scene.history.undo_len(), 1);
1969 assert_eq!(scene.undo(), Ok(true));
1970 assert_eq!((z(&scene, a, 1), z(&scene, b, 1)), (0.0, 0.0));
1971 }
1972
1973 #[test]
1974 fn undo_closes_open_step() {
1975 let mut scene = Scene::new(SceneOptions::default());
1976 let a = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
1977 lift(&mut scene, a, 4, 9.0);
1978 scene.begin_step();
1979 lift(&mut scene, a, 0, 1.0);
1980 lift(&mut scene, a, 0, 2.0);
1981 assert_eq!(scene.undo(), Ok(true));
1982 assert_eq!((z(&scene, a, 0), z(&scene, a, 4)), (0.0, 9.0));
1983 assert_eq!(scene.end_step(), Err(SceneError::StepNotOpen));
1984 assert_eq!(scene.redo(), Ok(true));
1985 assert_eq!(z(&scene, a, 0), 2.0);
1986 scene.begin_step();
1988 assert_eq!(scene.redo(), Ok(false));
1989 assert_eq!(scene.end_step(), Err(SceneError::StepNotOpen));
1990 scene.begin_step();
1991 lift(&mut scene, a, 1, 1.0);
1992 scene.clear_history().unwrap();
1993 assert_eq!(scene.end_step(), Err(SceneError::StepNotOpen));
1994 assert!(!scene.can_undo() && !scene.can_redo());
1995 assert_eq!(z(&scene, a, 1), 1.0);
1996 }
1997
1998 #[test]
1999 fn cancel_step_reverts_open_entries() {
2000 let mut scene = Scene::new(SceneOptions::default());
2001 let a = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2002 lift(&mut scene, a, 4, 9.0);
2003 assert_eq!(scene.cancel_step(), Err(SceneError::StepNotOpen));
2004 scene.take_changes();
2005 scene.begin_step();
2006 scene.begin_step();
2007 lift(&mut scene, a, 0, 1.0);
2008 scene.set_placement(a, moved(2.0)).unwrap();
2009 let v = scene
2010 .edit(a, |tx| tx.add_vertices(&[[5.0, 5.0, 5.0]]))
2011 .unwrap();
2012 scene.cancel_step().unwrap();
2013 assert_eq!(scene.end_step(), Err(SceneError::StepNotOpen));
2015 assert_eq!(scene.cancel_step(), Err(SceneError::StepNotOpen));
2016 assert_eq!((z(&scene, a, 0), z(&scene, a, 4)), (0.0, 9.0));
2017 assert_eq!(scene.placement(a), Ok(Placement::IDENTITY));
2018 assert!(!scene.mesh(a).unwrap().is_vertex_alive(v[0]));
2019 assert_eq!(scene.history.undo_len(), 1);
2020 assert!(!scene.can_redo());
2021 assert_valid(&scene, a);
2022 let ch = scene.take_changes();
2023 assert_eq!(ch.len(), 1);
2024 assert!(ch[0].placement_changed);
2025 let again = scene
2027 .edit(a, |tx| tx.add_vertices(&[[6.0, 6.0, 6.0]]))
2028 .unwrap();
2029 assert_eq!(again, v);
2030 }
2031
2032 #[test]
2033 fn new_step_clears_redo() {
2034 let mut scene = Scene::new(SceneOptions::default());
2035 let a = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2036 let b = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2037 let v = scene
2038 .edit(a, |tx| tx.add_vertices(&[[5.0, 5.0, 5.0]]))
2039 .unwrap();
2040 lift(&mut scene, a, 1, 1.0);
2041 scene.undo().unwrap();
2042 scene.undo().unwrap();
2043 assert!(scene.can_redo());
2044 scene.begin_step();
2046 scene.end_step().unwrap();
2047 assert!(scene.can_redo());
2048 lift(&mut scene, b, 0, 1.0);
2050 assert!(!scene.can_redo());
2051 assert_eq!(scene.redo(), Ok(false));
2052 assert_eq!(z(&scene, a, 1), 0.0);
2053 let again = scene
2055 .edit(a, |tx| tx.add_vertices(&[[6.0, 6.0, 6.0]]))
2056 .unwrap();
2057 assert_eq!(again, v);
2058 scene.undo().unwrap();
2060 assert!(scene.can_redo());
2061 scene.set_placement(b, moved(1.0)).unwrap();
2062 assert!(!scene.can_redo());
2063 }
2064
2065 #[test]
2066 fn step_undo_is_atomic() {
2067 let mut scene = Scene::new(SceneOptions::default());
2068 let a = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2069 let b = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2070 scene.begin_step();
2071 lift(&mut scene, a, 0, 1.0);
2072 scene.set_placement(b, moved(1.0)).unwrap();
2073 lift(&mut scene, b, 1, 2.0);
2074 scene.end_step().unwrap();
2075 scene.take_changes();
2076 let revs = |s: &Scene| (s.mesh(a).unwrap().revision(), s.mesh(b).unwrap().revision());
2077 let before = revs(&scene);
2078 let oom = Err(SceneError::Store(StoreError::OutOfMemory));
2079
2080 fault::fail_patch_on(2);
2083 assert_eq!(scene.undo(), oom);
2084 assert_eq!(revs(&scene), before);
2085 assert_eq!((z(&scene, a, 0), z(&scene, b, 1)), (1.0, 2.0));
2086 assert_eq!(scene.placement(b), Ok(moved(1.0)));
2087 assert!(scene.can_undo() && !scene.can_redo());
2088 assert_eq!(scene.history.undo_len(), 1);
2089 assert!(scene.take_changes().is_empty());
2090 assert_eq!(
2091 (scene.is_current(a), scene.is_current(b)),
2092 (Ok(true), Ok(true))
2093 );
2094 assert_valid(&scene, a);
2095 assert_valid(&scene, b);
2096
2097 fault::fail_patch_on(1);
2099 assert_eq!(scene.undo(), oom);
2100 assert_eq!(revs(&scene), before);
2101
2102 assert_eq!(scene.undo(), Ok(true));
2103 assert_eq!((z(&scene, a, 0), z(&scene, b, 1)), (0.0, 0.0));
2104 let undone = revs(&scene);
2105 scene.take_changes();
2106
2107 fault::fail_patch_on(2);
2109 assert_eq!(scene.redo(), oom);
2110 assert_eq!(revs(&scene), undone);
2111 assert_eq!((z(&scene, a, 0), z(&scene, b, 1)), (0.0, 0.0));
2112 assert_eq!(scene.placement(b), Ok(Placement::IDENTITY));
2113 assert!(!scene.can_undo() && scene.can_redo());
2114 assert!(scene.take_changes().is_empty());
2115 assert_eq!(scene.redo(), Ok(true));
2116 assert_eq!((z(&scene, a, 0), z(&scene, b, 1)), (1.0, 2.0));
2117
2118 scene.begin_step();
2120 lift(&mut scene, a, 2, 1.0);
2121 lift(&mut scene, b, 2, 1.0);
2122 fault::fail_patch_on(2);
2123 assert_eq!(scene.cancel_step(), oom.map(|_| ()));
2124 assert_eq!((z(&scene, a, 2), z(&scene, b, 2)), (1.0, 1.0));
2125 scene.cancel_step().unwrap();
2126 assert_eq!((z(&scene, a, 2), z(&scene, b, 2)), (0.0, 0.0));
2127 }
2128
2129 #[test]
2130 fn failed_recovery_reports_corrupted() {
2131 let mut scene = Scene::new(SceneOptions::default());
2132 let a = scene
2133 .add_mesh(grid(2), with_mode(UpdateMode::Lazy))
2134 .unwrap();
2135 let b = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2136 let c = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2137 scene.begin_step();
2138 lift(&mut scene, a, 0, 1.0);
2139 scene.set_placement(c, moved(1.0)).unwrap();
2140 lift(&mut scene, b, 1, 2.0);
2141 scene.end_step().unwrap();
2142 scene.flush().unwrap();
2143 scene.take_changes();
2144 let rev_a = scene.mesh(a).unwrap().revision();
2145 fault::fail_patch_on(2);
2148 fault::fail_patch_on(3);
2149 assert_eq!(scene.undo(), Err(SceneError::Corrupted));
2150 assert_eq!(scene.mesh(a).unwrap().revision(), rev_a);
2151 assert_eq!((z(&scene, a, 0), z(&scene, b, 1)), (1.0, 0.0));
2152
2153 let ch = scene.take_changes();
2157 assert_eq!(ch.iter().map(|c| c.id).collect::<Vec<_>>(), [a, b, c]);
2158 assert!(ch[..2].iter().all(|c| c.changes.is_none()));
2159 assert!(ch[2].placement_changed);
2160 assert_eq!(ch[2].changes.as_ref().map(ChangeSet::is_empty), Some(true));
2161 assert_eq!(scene.placement(c), Ok(moved(1.0)));
2162 assert_eq!(scene.is_current(b), Ok(true));
2165 assert_valid(&scene, b);
2166 assert_eq!(scene.is_current(a), Ok(false));
2167 scene.flush().unwrap();
2168 assert_eq!(scene.is_current(a), Ok(true));
2169 assert_valid(&scene, a);
2170 assert!(!scene.entries.get(a).unwrap().rebuild);
2171
2172 scene.clear_history().unwrap();
2174 assert!(!scene.can_undo() && !scene.can_redo());
2175 lift(&mut scene, b, 2, 1.0);
2176 assert_eq!(scene.undo(), Ok(true));
2177 assert_eq!(z(&scene, b, 2), 0.0);
2178 assert_valid(&scene, b);
2179 }
2180
2181 #[test]
2185 fn corrupted_step_is_dropped() {
2186 let mut scene = Scene::new(SceneOptions::default());
2187 let a = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2188 scene.begin_step();
2189 lift(&mut scene, a, 0, 1.0);
2190 lift(&mut scene, a, 1, 2.0);
2191 scene.end_step().unwrap();
2192 scene.take_changes();
2193 fault::fail_patch_on(2);
2196 fault::fail_patch_on(3);
2197 assert_eq!(scene.undo(), Err(SceneError::Corrupted));
2198 let ch = scene.take_changes();
2201 assert_eq!(ch.len(), 1);
2202 assert!(ch[0].changes.is_none());
2203 assert!(!scene.can_undo() && !scene.can_redo());
2204 assert_eq!(scene.history.bytes(), 0);
2205 assert!(scene.entries.get(a).unwrap().wbox.is_none());
2208 scene
2209 .raycast(
2210 [0.0, 0.0, 5.0],
2211 [0.0, 0.0, -1.0],
2212 &crate::SceneRayOptions::default(),
2213 )
2214 .unwrap();
2215 assert!(scene.entries.get(a).unwrap().wbox.is_some());
2216 lift(&mut scene, a, 2, 1.0);
2217 assert_eq!(scene.undo(), Ok(true));
2218 assert_eq!(z(&scene, a, 2), 0.0);
2219 }
2220
2221 #[test]
2223 fn corrupted_redo_step_is_dropped() {
2224 let mut scene = Scene::new(SceneOptions::default());
2225 let a = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2226 scene.begin_step();
2227 lift(&mut scene, a, 0, 1.0);
2228 lift(&mut scene, a, 1, 2.0);
2229 scene.end_step().unwrap();
2230 assert_eq!(scene.undo(), Ok(true));
2231 assert_eq!((z(&scene, a, 0), z(&scene, a, 1)), (0.0, 0.0));
2232 scene.take_changes();
2233 fault::fail_patch_on(2);
2236 fault::fail_patch_on(3);
2237 assert_eq!(scene.redo(), Err(SceneError::Corrupted));
2238 let ch = scene.take_changes();
2239 assert_eq!(ch.len(), 1);
2240 assert!(ch[0].changes.is_none());
2241 assert!(!scene.can_undo() && !scene.can_redo());
2242 assert_eq!(scene.history.bytes(), 0);
2243 lift(&mut scene, a, 2, 1.0);
2244 assert_eq!(scene.undo(), Ok(true));
2245 assert_eq!(z(&scene, a, 2), 0.0);
2246 }
2247
2248 #[test]
2250 fn corrupted_cancel_discards_the_open_step() {
2251 let mut scene = Scene::new(SceneOptions::default());
2252 let a = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2253 scene.begin_step();
2254 lift(&mut scene, a, 0, 1.0);
2255 lift(&mut scene, a, 1, 2.0);
2256 scene.take_changes();
2257 fault::fail_patch_on(2);
2258 fault::fail_patch_on(3);
2259 assert_eq!(scene.cancel_step(), Err(SceneError::Corrupted));
2260 let ch = scene.take_changes();
2261 assert_eq!(ch.len(), 1);
2262 assert!(ch[0].changes.is_none());
2263 assert_eq!(scene.end_step(), Err(SceneError::StepNotOpen));
2265 assert!(!scene.can_undo() && !scene.can_redo());
2266 assert_eq!(scene.history.bytes(), 0);
2267 lift(&mut scene, a, 2, 1.0);
2268 assert_eq!(scene.undo(), Ok(true));
2269 }
2270
2271 #[test]
2273 fn corrupted_undo_of_open_step_discards_it() {
2274 let mut scene = Scene::new(SceneOptions::default());
2275 let a = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2276 scene.begin_step();
2277 lift(&mut scene, a, 0, 1.0);
2278 lift(&mut scene, a, 1, 2.0);
2279 scene.take_changes();
2280 fault::fail_patch_on(2);
2281 fault::fail_patch_on(3);
2282 assert_eq!(scene.undo(), Err(SceneError::Corrupted));
2283 let ch = scene.take_changes();
2284 assert_eq!(ch.len(), 1);
2285 assert!(ch[0].changes.is_none());
2286 assert_eq!(scene.end_step(), Err(SceneError::StepNotOpen));
2287 assert!(!scene.can_undo() && !scene.can_redo());
2288 assert_eq!(scene.history.bytes(), 0);
2289 lift(&mut scene, a, 2, 1.0);
2290 assert_eq!(scene.undo(), Ok(true));
2291 }
2292
2293 #[test]
2296 fn corrupted_step_releases_only_known_slots() {
2297 let mut scene = Scene::new(SceneOptions::default());
2298 let a = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2299 scene.begin_step();
2300 scene.edit(a, |tx| tx.remove_triangles(&[0])).unwrap();
2303 scene.edit(a, |tx| tx.remove_triangles(&[1])).unwrap();
2304 scene.edit(a, |tx| tx.remove_triangles(&[2])).unwrap();
2305 let v = scene
2306 .edit(a, |tx| tx.add_vertices(&[[9.0, 9.0, 9.0]]))
2307 .unwrap()[0];
2308 assert_eq!(v, 9);
2309 scene.end_step().unwrap();
2310 scene.take_changes();
2311 fault::fail_patch_on(3);
2315 fault::fail_patch_on(4);
2316 assert_eq!(scene.undo(), Err(SceneError::Corrupted));
2317 assert!(!scene.can_undo());
2318 let mesh = scene.mesh(a).unwrap();
2319 assert!(mesh.free_vertex_slots().contains(&9));
2320 assert!(mesh.free_triangle_slots().contains(&0));
2321 assert!(!mesh.free_triangle_slots().contains(&1));
2322 assert!(!mesh.free_triangle_slots().contains(&2));
2323 }
2324
2325 #[test]
2329 fn corrupted_step_rebuilds_once_and_reports_placements() {
2330 let mut scene = Scene::new(SceneOptions::default());
2331 let a = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2332 let b = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2333 let c = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2334 scene.begin_step();
2335 for k in 0..3 {
2336 lift(&mut scene, a, k, 1.0);
2337 lift(&mut scene, b, k, 1.0);
2338 }
2339 scene.set_placement(c, moved(1.0)).unwrap();
2340 scene.end_step().unwrap();
2341 scene.take_changes();
2342 fault::take_rebuilds();
2343 fault::fail_patch_on(2);
2346 fault::fail_patch_on(3);
2347 assert_eq!(scene.undo(), Err(SceneError::Corrupted));
2348 assert_eq!(scene.placement(c), Ok(Placement::IDENTITY));
2349 assert_eq!(fault::take_rebuilds(), 2);
2351 for id in [a, b] {
2352 assert_eq!(scene.is_current(id), Ok(true));
2353 assert_valid(&scene, id);
2354 }
2355 let ch = scene.take_changes();
2356 assert_eq!(ch.iter().map(|c| c.id).collect::<Vec<_>>(), [a, b, c]);
2357 assert!(ch[..2].iter().all(|c| c.changes.is_none()));
2358 assert!(ch[2].placement_changed);
2359 assert_eq!(ch[2].changes.as_ref().map(ChangeSet::is_empty), Some(true));
2360 }
2361
2362 #[test]
2365 fn undo_of_over_budget_open_step_still_undoes() {
2366 let mut scene = Scene::new(SceneOptions {
2367 history_budget: 1000,
2368 });
2369 let a = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2370 let b = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2371 scene.begin_step();
2373 for k in 1..=20 {
2374 scene.set_placement(a, moved(f64::from(k))).unwrap();
2375 }
2376 assert!(scene.can_undo());
2377 assert_eq!(scene.undo(), Ok(true));
2378 assert_eq!(scene.placement(a), Ok(Placement::IDENTITY));
2379 assert_eq!(scene.end_step(), Err(SceneError::StepNotOpen));
2380
2381 lift(&mut scene, a, 4, 3.0);
2383 scene.begin_step();
2384 for k in 1..=10 {
2385 scene.set_placement(a, moved(f64::from(k))).unwrap();
2386 scene.set_placement(b, moved(f64::from(-k))).unwrap();
2387 }
2388 assert!(scene.history.bytes() > 1000);
2389 assert!(scene.can_undo());
2390 scene.take_changes();
2391 assert_eq!(scene.undo(), Ok(true));
2392 assert_eq!(scene.placement(a), Ok(Placement::IDENTITY));
2393 assert_eq!(scene.placement(b), Ok(Placement::IDENTITY));
2394 assert_eq!(scene.end_step(), Err(SceneError::StepNotOpen));
2395 let ch = scene.take_changes();
2396 assert_eq!(ch.len(), 2);
2397 assert!(ch.iter().all(|c| c.placement_changed));
2398 assert!(!scene.can_undo() && !scene.can_redo());
2401 assert_eq!(scene.history.bytes(), 0);
2402 assert_eq!(z(&scene, a, 4), 3.0);
2403
2404 scene.begin_step();
2406 scene.set_placement(b, moved(2.0)).unwrap();
2407 assert_eq!(scene.undo(), Ok(true));
2408 assert!(scene.can_redo());
2409 assert_eq!(scene.redo(), Ok(true));
2410 assert_eq!(scene.placement(b), Ok(moved(2.0)));
2411 }
2412
2413 #[test]
2416 fn unchanged_placement_is_not_reported() {
2417 let mut scene = Scene::new(SceneOptions::default());
2418 let a = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2419 scene.take_changes();
2420 scene.set_placement(a, Placement::IDENTITY).unwrap();
2421 assert!(scene.take_changes().is_empty());
2422 assert!(!scene.can_undo());
2423 scene.set_placement(a, moved(1.0)).unwrap();
2424 scene.take_changes();
2425 scene.set_placement(a, moved(1.0)).unwrap();
2426 assert!(scene.take_changes().is_empty());
2427 assert_eq!(scene.history.undo_len(), 1);
2428 }
2429
2430 #[test]
2432 fn placement_runs_coalesce_in_open_step() {
2433 let mut scene = Scene::new(SceneOptions::default());
2434 let a = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2435 let b = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2436 let bytes = crate::history::PLACEMENT_BYTES;
2437
2438 scene.begin_step();
2440 for k in 1..=300 {
2441 scene.set_placement(a, moved(f64::from(k))).unwrap();
2442 }
2443 assert_eq!(scene.history.bytes(), bytes);
2444 scene.end_step().unwrap();
2445 assert_eq!(step_bytes(&scene), [bytes]);
2446 assert_eq!(scene.undo(), Ok(true));
2447 assert_eq!(scene.placement(a), Ok(Placement::IDENTITY));
2448 assert_eq!(scene.redo(), Ok(true));
2449 assert_eq!(scene.placement(a), Ok(moved(300.0)));
2450
2451 scene.begin_step();
2453 scene.set_placement(a, moved(1.0)).unwrap();
2454 scene.set_placement(a, moved(2.0)).unwrap();
2455 lift(&mut scene, a, 0, 1.0);
2456 scene.set_placement(a, moved(3.0)).unwrap();
2457 scene.set_placement(b, moved(4.0)).unwrap();
2458 scene.set_placement(a, moved(5.0)).unwrap();
2459 scene.set_placement(a, moved(6.0)).unwrap();
2460 scene.end_step().unwrap();
2461 let last = *step_bytes(&scene).last().unwrap();
2462 let edit = last - 4 * bytes;
2463 assert!(edit > 0 && edit != bytes, "{last}");
2464 assert_eq!(scene.undo(), Ok(true));
2466 assert_eq!(scene.placement(a), Ok(moved(300.0)));
2467 assert_eq!(scene.placement(b), Ok(Placement::IDENTITY));
2468 assert_eq!(z(&scene, a, 0), 0.0);
2469 assert_eq!(scene.redo(), Ok(true));
2470 assert_eq!(scene.placement(a), Ok(moved(6.0)));
2471 assert_eq!(scene.placement(b), Ok(moved(4.0)));
2472
2473 let before = scene.history.undo_len();
2475 scene.set_placement(a, moved(7.0)).unwrap();
2476 scene.set_placement(a, moved(8.0)).unwrap();
2477 assert_eq!(scene.history.undo_len(), before + 2);
2478
2479 scene.begin_step();
2481 for k in 0..10 {
2482 scene.set_placement(b, moved(f64::from(k) + 0.5)).unwrap();
2483 }
2484 scene.cancel_step().unwrap();
2485 assert_eq!(scene.placement(b), Ok(moved(4.0)));
2486
2487 scene.begin_step();
2490 scene.set_placement(b, moved(9.0)).unwrap();
2491 scene.set_placement(b, moved(4.0)).unwrap();
2492 scene.end_step().unwrap();
2493 scene.take_changes();
2494 assert_eq!(scene.undo(), Ok(true));
2495 assert_eq!(scene.placement(b), Ok(moved(4.0)));
2496 let ch = scene.take_changes();
2497 assert_eq!(ch.len(), 1);
2498 assert!(ch[0].placement_changed);
2499 }
2500
2501 #[test]
2503 fn failed_undo_or_redo_keeps_open_step() {
2504 let mut scene = Scene::new(SceneOptions::default());
2505 let a = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2506 let oom = Err(SceneError::Store(StoreError::OutOfMemory));
2507
2508 lift(&mut scene, a, 0, 1.0);
2510 scene.begin_step();
2511 lift(&mut scene, a, 1, 1.0);
2512 fault::fail_patch_on(1);
2513 assert_eq!(scene.undo(), oom);
2514 assert_eq!((z(&scene, a, 0), z(&scene, a, 1)), (1.0, 1.0));
2515 lift(&mut scene, a, 2, 1.0);
2516 assert_eq!(scene.end_step(), Ok(()));
2517 assert_eq!(scene.history.undo_len(), 2);
2518 assert_eq!(scene.undo(), Ok(true));
2519 assert_eq!((z(&scene, a, 1), z(&scene, a, 2)), (0.0, 0.0));
2520
2521 scene.begin_step();
2523 fault::fail_patch_on(1);
2524 assert_eq!(scene.undo(), oom);
2525 assert_eq!(scene.end_step(), Ok(()));
2526 assert_eq!(z(&scene, a, 0), 1.0);
2527
2528 scene.begin_step();
2530 fault::fail_patch_on(1);
2531 assert_eq!(scene.redo(), oom);
2532 assert_eq!(scene.end_step(), Ok(()));
2533 assert_eq!((z(&scene, a, 1), z(&scene, a, 2)), (0.0, 0.0));
2534 assert_eq!(scene.redo(), Ok(true));
2535 assert_eq!((z(&scene, a, 1), z(&scene, a, 2)), (1.0, 1.0));
2536 }
2537
2538 #[test]
2540 fn failed_reservation_changes_nothing() {
2541 let mut scene = Scene::new(SceneOptions::default());
2542 let a = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2543 lift(&mut scene, a, 0, 1.0);
2544 scene.take_changes();
2545 let oom: Result<()> = Err(SceneError::Store(StoreError::OutOfMemory));
2546
2547 fault::fail_reserve_on(1);
2550 assert_eq!(
2551 scene.edit(a, |tx| tx.set_positions(&[1], &[[1.0, 0.0, 2.0]])),
2552 oom
2553 );
2554 assert_eq!((z(&scene, a, 0), z(&scene, a, 1)), (1.0, 0.0));
2555 assert!(scene.take_changes().is_empty());
2556 assert_eq!(scene.history.undo_len(), 1);
2557
2558 fault::fail_reserve_on(1);
2560 assert_eq!(scene.set_placement(a, moved(1.0)), oom);
2561 assert_eq!(scene.placement(a), Ok(Placement::IDENTITY));
2562 assert!(scene.take_changes().is_empty());
2563 assert_eq!(scene.history.undo_len(), 1);
2564
2565 lift(&mut scene, a, 1, 2.0);
2567 assert_eq!(z(&scene, a, 1), 2.0);
2568 assert_eq!(scene.history.undo_len(), 2);
2569 assert_eq!(scene.undo(), Ok(true));
2570 assert_eq!(z(&scene, a, 1), 0.0);
2571 }
2572
2573 fn step_bytes(scene: &Scene) -> Vec<usize> {
2575 scene.history.undo_step_bytes().collect()
2576 }
2577
2578 #[test]
2579 fn budget_evicts_oldest_steps_and_releases_slots() {
2580 let remove_three = |scene: &mut Scene, id: MeshId| {
2581 for t in 0..3 {
2582 scene.edit(id, |tx| tx.remove_triangles(&[t])).unwrap();
2583 }
2584 };
2585 let mut probe = Scene::new(SceneOptions::default());
2586 let p = probe.add_mesh(grid(3), MeshOptions::default()).unwrap();
2587 remove_three(&mut probe, p);
2588 let sizes = step_bytes(&probe);
2589 assert_eq!(sizes.len(), 3);
2590 assert!(sizes.iter().all(|&s| s > 0));
2591
2592 let mut scene = Scene::new(SceneOptions {
2594 history_budget: sizes[1] + sizes[2],
2595 });
2596 let id = scene.add_mesh(grid(3), MeshOptions::default()).unwrap();
2597 remove_three(&mut scene, id);
2598 assert_eq!(step_bytes(&scene), sizes[1..]);
2599 assert_eq!(scene.history.bytes(), sizes[1] + sizes[2]);
2600 assert_eq!(scene.mesh(id).unwrap().free_triangle_slots(), [0]);
2602 assert_eq!(scene.undo(), Ok(true));
2603 assert_eq!(scene.undo(), Ok(true));
2604 assert_eq!(scene.undo(), Ok(false));
2605 let m = scene.mesh(id).unwrap();
2606 assert!(!m.is_triangle_alive(0) && m.is_triangle_alive(1) && m.is_triangle_alive(2));
2607 let t = scene.edit(id, |tx| tx.add_triangles(&[[0, 1, 4]])).unwrap();
2609 assert_eq!(t, [0]);
2610
2611 let mut zero = Scene::new(SceneOptions { history_budget: 0 });
2613 let id = zero.add_mesh(grid(3), MeshOptions::default()).unwrap();
2614 zero.begin_step();
2615 zero.edit(id, |tx| tx.remove_triangles(&[4])).unwrap();
2616 assert!(zero.can_undo());
2617 zero.end_step().unwrap();
2618 assert!(!zero.can_undo());
2619 assert_eq!(zero.history.bytes(), 0);
2620 assert_eq!(zero.mesh(id).unwrap().free_triangle_slots(), [4]);
2621
2622 let mut scene = Scene::new(SceneOptions::default());
2624 let id = scene.add_mesh(grid(3), MeshOptions::default()).unwrap();
2625 scene.edit(id, |tx| tx.remove_triangles(&[2])).unwrap();
2626 let v = scene
2627 .edit(id, |tx| tx.add_vertices(&[[9.0, 9.0, 9.0]]))
2628 .unwrap();
2629 scene.undo().unwrap();
2630 scene.clear_history().unwrap();
2631 assert!(!scene.can_undo() && !scene.can_redo());
2632 assert_eq!(scene.history.bytes(), 0);
2633 let m = scene.mesh(id).unwrap();
2634 assert_eq!(m.free_triangle_slots(), [2]);
2635 assert_eq!(m.free_vertex_slots(), v);
2636
2637 scene.set_placement(id, moved(1.0)).unwrap();
2639 assert_eq!(scene.history.bytes(), crate::history::PLACEMENT_BYTES);
2640 }
2641
2642 #[test]
2643 fn history_survives_remove_and_compact() {
2644 let mut scene = Scene::new(SceneOptions::default());
2645 let a = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2646 let b = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2647 let c = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2648 scene.begin_step();
2649 lift(&mut scene, a, 0, 1.0);
2650 scene.edit(b, |tx| tx.remove_triangles(&[0])).unwrap();
2651 lift(&mut scene, c, 0, 1.0);
2652 scene.end_step().unwrap();
2653 lift(&mut scene, b, 1, 1.0);
2654 let vb = scene
2655 .edit(b, |tx| tx.add_vertices(&[[7.0, 7.0, 7.0]]))
2656 .unwrap();
2657 scene.undo().unwrap();
2658 assert_eq!(scene.history.undo_len(), 2);
2659
2660 let mb = scene.remove_mesh(b).unwrap();
2663 assert_eq!(mb.free_triangle_slots(), [0]);
2664 assert_eq!(mb.free_vertex_slots(), vb);
2665 assert_eq!(scene.history.undo_len(), 1);
2666 assert!(!scene.can_redo());
2667
2668 lift(&mut scene, c, 1, 1.0);
2671 scene.set_placement(c, moved(1.0)).unwrap();
2672 assert_eq!(scene.history.undo_len(), 3);
2673 scene.compact(c).unwrap();
2674 assert_eq!(scene.history.undo_len(), 2);
2675 assert_eq!(scene.undo(), Ok(true));
2676 assert_eq!(scene.placement(c), Ok(Placement::IDENTITY));
2677 assert_eq!(scene.undo(), Ok(true));
2678 assert_eq!(z(&scene, a, 0), 0.0);
2679 assert_eq!((z(&scene, c, 0), z(&scene, c, 1)), (1.0, 1.0));
2680 assert_eq!(scene.undo(), Ok(false));
2681 assert_eq!(scene.redo(), Ok(true));
2682 assert_eq!(z(&scene, a, 0), 1.0);
2683 assert_eq!(scene.redo(), Ok(true));
2684 assert_eq!(scene.placement(c), Ok(moved(1.0)));
2685
2686 scene.begin_step();
2688 lift(&mut scene, a, 1, 1.0);
2689 lift(&mut scene, c, 2, 1.0);
2690 scene.remove_mesh(c).unwrap();
2691 scene.end_step().unwrap();
2692 assert_eq!(scene.undo(), Ok(true));
2693 assert_eq!(z(&scene, a, 1), 0.0);
2694 assert_eq!(scene.history.undo_len(), 1);
2695 assert_valid(&scene, a);
2696 }
2697
2698 #[test]
2702 fn manual_bvh_current_by_revision_with_pending_changes() {
2703 let mut scene = Scene::new(SceneOptions::default());
2704 let m = scene
2705 .add_mesh(grid(4), with_mode(UpdateMode::Manual))
2706 .unwrap();
2707 lift(&mut scene, m, 6, 1.0);
2708 assert_eq!(scene.is_current(m), Ok(false));
2709 scene.undo().unwrap();
2710 assert_eq!(scene.is_current(m), Ok(true));
2711 assert!(scene.entries.get(m).unwrap().pending.is_some());
2712
2713 lift(&mut scene, m, 7, 2.0);
2714 assert_eq!(scene.is_current(m), Ok(false));
2715 scene.update(m).unwrap();
2716 assert_eq!(scene.is_current(m), Ok(true));
2717 assert_valid(&scene, m);
2718
2719 let points = [[1.0, 1.0, 3.0], [2.5, 1.5, -1.0], [0.0, 4.0, 0.5]];
2720 let e = scene.entries.get(m).unwrap();
2721 let fresh = Bvh::build(&e.mesh, &BuildOptions::default()).unwrap();
2722 let wants = points.map(|p| {
2723 fast_mesh_query::closest_point(
2724 &e.mesh,
2725 &fresh,
2726 p,
2727 &fast_mesh_query::ClosestOptions::default(),
2728 )
2729 .unwrap()
2730 .map(|h| (h.triangle, h.distance))
2731 });
2732 for (p, want) in points.into_iter().zip(wants) {
2733 let got = scene
2734 .closest_point_on(m, p.map(f64::from), &crate::SceneClosestOptions::default())
2735 .unwrap()
2736 .map(|h| (h.hit.triangle, h.hit.distance));
2737 assert_eq!(got, want);
2738 }
2739 }
2740
2741 #[test]
2742 fn undo_updates_bvhs_per_mode() {
2743 let mut scene = Scene::new(SceneOptions::default());
2744 let e = scene.add_mesh(grid(4), MeshOptions::default()).unwrap();
2745 let l = scene
2746 .add_mesh(grid(4), with_mode(UpdateMode::Lazy))
2747 .unwrap();
2748 let m = scene
2749 .add_mesh(grid(4), with_mode(UpdateMode::Manual))
2750 .unwrap();
2751 scene.begin_step();
2752 for id in [e, l, m] {
2753 lift(&mut scene, id, 6, 1.0);
2754 }
2755 scene.end_step().unwrap();
2756 scene.flush().unwrap();
2757 scene.update(m).unwrap();
2758 scene.take_changes();
2759
2760 let check = |scene: &mut Scene| {
2761 assert_eq!(scene.is_current(e), Ok(true));
2762 assert_eq!(scene.is_current(l), Ok(false));
2763 assert_eq!(scene.is_current(m), Ok(false));
2764 let ch = scene.take_changes();
2765 assert_eq!(ch.len(), 3);
2766 assert!(
2767 ch.iter()
2768 .all(|c| c.changes.as_ref().unwrap().vertices_moved == [6])
2769 );
2770 scene.flush().unwrap();
2771 assert_eq!(scene.is_current(l), Ok(true));
2772 assert_eq!(scene.is_current(m), Ok(false));
2773 scene.update(m).unwrap();
2774 for id in [e, l, m] {
2775 assert_valid(scene, id);
2776 }
2777 };
2778 scene.undo().unwrap();
2779 check(&mut scene);
2780 scene.redo().unwrap();
2781 check(&mut scene);
2782
2783 fault::fail_bvh_update_on(1);
2785 assert_eq!(scene.undo(), Ok(true));
2786 assert_eq!(scene.is_current(e), Ok(false));
2787 assert!(scene.entries.get(e).unwrap().pending.is_some());
2788 scene.flush().unwrap();
2789 assert_eq!(scene.is_current(e), Ok(true));
2790 assert_valid(&scene, e);
2791 }
2792
2793 #[test]
2794 fn two_subscribers_each_get_all_changes() {
2795 let mut scene = Scene::new(SceneOptions::default());
2796 let a = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2797 let b = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2798 let s = scene.subscribe();
2800 assert_eq!(scene.take_changes_for(s), Ok(Vec::new()));
2801 assert_eq!(scene.take_changes().len(), 2);
2802
2803 lift(&mut scene, a, 4, 1.0);
2804 scene.set_placement(b, moved(1.0)).unwrap();
2805 let mine = scene.take_changes();
2806 assert_eq!(mine.len(), 2);
2807 lift(&mut scene, a, 1, 1.0);
2809 let theirs = scene.take_changes_for(s).unwrap();
2810 assert_eq!(theirs.len(), 2);
2811 assert_eq!(theirs[0].id, a);
2812 assert_eq!(theirs[0].changes.as_ref().unwrap().vertices_moved, [1, 4]);
2813 assert_eq!(theirs[0].colors_dirty, Some(Vec::new()));
2814 assert!(theirs[0].fields_changed.is_empty());
2815 assert!(theirs[1].placement_changed && theirs[1].id == b);
2816 let mine = scene.take_changes();
2817 assert_eq!(mine.len(), 1);
2818 assert_eq!(mine[0].changes.as_ref().unwrap().vertices_moved, [1]);
2819
2820 let s2 = scene.subscribe();
2822 assert_ne!(s, s2);
2823 let c = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2824 scene.compact(b).unwrap();
2825 scene.remove_mesh(a).unwrap();
2826 for got in [
2827 scene.take_changes(),
2828 scene.take_changes_for(s).unwrap(),
2829 scene.take_changes_for(s2).unwrap(),
2830 ] {
2831 assert_eq!(got.len(), 3, "{got:?}");
2832 assert!(got[0].id == a && got[0].removed);
2833 assert!(got[1].id == b && got[1].changes.is_none() && !got[1].added);
2834 assert!(got[2].id == c && got[2].added);
2835 }
2836 assert!(scene.take_changes_for(s2).unwrap().is_empty());
2837 }
2838
2839 #[test]
2842 fn add_then_remove_is_per_subscriber() {
2843 let mut scene = Scene::new(SceneOptions::default());
2844 let s = scene.subscribe();
2845 let id = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2846 let added = scene.take_changes_for(s).unwrap();
2847 assert!(added[0].added && added[0].colors_dirty.is_none());
2848 lift(&mut scene, id, 0, 1.0);
2849 scene.remove_mesh(id).unwrap();
2850 let got = scene.take_changes_for(s).unwrap();
2851 assert_eq!(got.len(), 1);
2852 assert!(got[0].id == id && got[0].removed && !got[0].added);
2853 assert_eq!(got[0].changes.as_ref().unwrap().vertices_moved, [0]);
2854 assert!(scene.take_changes().is_empty());
2855 }
2856
2857 #[test]
2858 fn unsubscribed_id_rejected() {
2859 let mut scene = Scene::new(SceneOptions::default());
2860 let a = scene.add_mesh(grid(2), MeshOptions::default()).unwrap();
2861 scene.take_changes();
2862 let s = scene.subscribe();
2863 let keep = scene.subscribe();
2864 scene.unsubscribe(s).unwrap();
2865 assert!(matches!(
2866 scene.take_changes_for(s),
2867 Err(SceneError::InvalidInput(_))
2868 ));
2869 assert!(matches!(
2870 scene.unsubscribe(s),
2871 Err(SceneError::InvalidInput(_))
2872 ));
2873 lift(&mut scene, a, 0, 1.0);
2875 scene.remove_mesh(a).unwrap();
2876 assert_eq!(scene.take_changes_for(keep).unwrap().len(), 1);
2877 assert_eq!(scene.take_changes().len(), 1);
2878 assert!(scene.subscribe() != s);
2880 }
2881
2882 #[test]
2883 fn channel_writes_are_reported() {
2884 let mut scene = Scene::new(SceneOptions::default());
2885 let id = scene.add_mesh(grid(1), MeshOptions::default()).unwrap();
2886 let s = scene.subscribe();
2887 scene.take_changes();
2888 scene
2889 .add_channel(id, ChannelDesc::derived("curv", 1))
2890 .unwrap();
2891 scene
2892 .add_channel(id, ChannelDesc::derived("other", 1))
2893 .unwrap();
2894 scene.derived_channel_mut(id, "curv").unwrap()[0] = 1.0;
2895 scene.derived_channel_mut(id, "curv").unwrap()[1] = 1.0;
2896 let ch = scene.take_changes();
2897 assert_eq!(ch.len(), 1);
2898 assert_eq!(ch[0].channels_written, ["curv", "other"]);
2899 assert_eq!(ch[0].changes.as_ref().map(ChangeSet::is_empty), Some(true));
2900 assert!(!ch[0].placement_changed && !ch[0].added);
2901 scene.remove_channel(id, "other").unwrap();
2902 assert!(scene.derived_channel_mut(id, "nope").is_err());
2904 assert!(scene.remove_channel(id, "nope").is_err());
2905 assert_eq!(scene.take_changes()[0].channels_written, ["other"]);
2906 assert!(scene.take_changes().is_empty());
2907 assert_eq!(
2908 scene.take_changes_for(s).unwrap()[0].channels_written,
2909 ["curv", "other"]
2910 );
2911 }
2912
2913 #[test]
2914 fn field_prefix_is_reserved() {
2915 let mut scene = Scene::new(SceneOptions::default());
2916 let id = scene.add_mesh(grid(1), MeshOptions::default()).unwrap();
2917 scene.take_changes();
2918 assert!(matches!(
2919 scene.add_channel(id, ChannelDesc::derived("field:d", 1)),
2920 Err(SceneError::InvalidInput(_))
2921 ));
2922 assert!(scene.mesh(id).unwrap().channel("field:d").is_none());
2923 assert!(matches!(
2924 scene.remove_channel(id, "field:d"),
2925 Err(SceneError::InvalidInput(_))
2926 ));
2927 assert!(matches!(
2928 scene.derived_channel_mut(id, "field:d"),
2929 Err(SceneError::InvalidInput(_))
2930 ));
2931 assert!(scene.take_changes().is_empty());
2932 scene
2934 .add_channel(id, ChannelDesc::derived("fields", 1))
2935 .unwrap();
2936 }
2937
2938 fn sheet(n: u32) -> Mesh {
2940 let mut positions = Vec::new();
2941 for y in 0..=n {
2942 for x in 0..=n {
2943 let (fx, fy) = (x as f32 * 0.1, y as f32 * 0.1);
2944 positions.extend([fx, fy, (fx * 3.1).sin() * (fy * 1.7).cos() * 0.2]);
2945 }
2946 }
2947 let mut indices = Vec::new();
2948 for y in 0..n {
2949 for x in 0..n {
2950 let a = y * (n + 1) + x;
2951 indices.extend([a, a + 1, a + n + 2, a, a + n + 2, a + n + 1]);
2952 }
2953 }
2954 Mesh::from_buffers(&positions, &indices).unwrap()
2955 }
2956
2957 #[test]
2958 fn mesh_built_in_steps_matches_add_mesh() {
2959 let opts = MeshOptions {
2963 placement: Placement {
2964 rotation: [[0.0, -1.0, 0.0], [1.0, 0.0, 0.0], [0.0, 0.0, 1.0]],
2965 translation: [0.5, 0.1, -0.2],
2966 ..Placement::IDENTITY
2967 },
2968 ..MeshOptions::default()
2969 };
2970 for budget in [1, 97, 5000, usize::MAX] {
2971 let mut twins: Vec<(Scene, MeshId)> = (0..2)
2972 .map(|_| {
2973 let mut scene = Scene::new(SceneOptions::default());
2974 let gone = scene.add_mesh(tri(), MeshOptions::default()).unwrap();
2975 let other = scene.add_mesh(sheet(6), MeshOptions::default()).unwrap();
2976 scene.remove_mesh(gone).unwrap();
2977 scene.take_changes();
2978 (scene, other)
2979 })
2980 .collect();
2981 let mut build = MeshBuild::new(sheet(30), opts).unwrap();
2982 let mut steps = 0;
2983 while !build.step(budget).unwrap() {
2984 steps += 1;
2985 if steps == 3 {
2986 let (scene, other) = &mut twins[1];
2987 scene
2988 .set_placement(
2989 *other,
2990 Placement {
2991 translation: [0.0, 0.0, 0.3],
2992 ..Placement::IDENTITY
2993 },
2994 )
2995 .unwrap();
2996 scene
2997 .edit(*other, |tx| tx.set_positions(&[0], &[[0.0, 0.0, 0.1]]))
2998 .unwrap();
2999 }
3000 }
3001 if steps < 3 {
3002 let (scene, other) = &mut twins[1];
3003 scene
3004 .set_placement(
3005 *other,
3006 Placement {
3007 translation: [0.0, 0.0, 0.3],
3008 ..Placement::IDENTITY
3009 },
3010 )
3011 .unwrap();
3012 scene
3013 .edit(*other, |tx| tx.set_positions(&[0], &[[0.0, 0.0, 0.1]]))
3014 .unwrap();
3015 }
3016 if budget == 1 {
3017 assert!(steps > 100, "{steps}");
3018 }
3019 let built = twins[1].0.add_mesh_built(build).unwrap();
3020 let (scene, other) = &mut twins[0];
3021 scene
3022 .set_placement(
3023 *other,
3024 Placement {
3025 translation: [0.0, 0.0, 0.3],
3026 ..Placement::IDENTITY
3027 },
3028 )
3029 .unwrap();
3030 scene
3031 .edit(*other, |tx| tx.set_positions(&[0], &[[0.0, 0.0, 0.1]]))
3032 .unwrap();
3033 let added = scene.add_mesh(sheet(30), opts).unwrap();
3034 assert_eq!(added, built, "the same slot");
3035 let [(a, _), (b, _)] = &mut twins[..] else {
3036 unreachable!()
3037 };
3038 assert_eq!(a.take_changes(), b.take_changes());
3039 let (ba, bb) = (a.bvh(added).unwrap(), b.bvh(built).unwrap());
3040 assert_eq!((ba.node_count(), ba.depth()), (bb.node_count(), bb.depth()));
3041 assert_eq!(ba.root_bounds(), bb.root_bounds());
3042 bb.validate(b.mesh(built).unwrap()).unwrap();
3043 for k in 0..20 {
3044 let p = [0.1 * f64::from(k) - 0.5, 0.15 * f64::from(k), 0.3];
3045 let o = crate::SceneClosestOptions::default();
3046 assert_eq!(
3047 a.closest_point(p, &o).unwrap(),
3048 b.closest_point(p, &o).unwrap()
3049 );
3050 }
3051 }
3052 let bad = MeshOptions {
3054 placement: Placement {
3055 rotation: [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]],
3056 translation: [0.0; 3],
3057 ..Placement::IDENTITY
3058 },
3059 ..MeshOptions::default()
3060 };
3061 assert!(matches!(
3062 MeshBuild::new(tri(), bad),
3063 Err(SceneError::InvalidInput(_))
3064 ));
3065 }
3066
3067 #[test]
3068 fn invalid_bvh_policy_is_refused_before_the_build() {
3069 let bad = MeshOptions {
3070 bvh_policy: UpdatePolicy {
3071 full_rebuild_fraction: 2.0,
3072 ..UpdatePolicy::default()
3073 },
3074 ..MeshOptions::default()
3075 };
3076 let mut scene = Scene::new(SceneOptions::default());
3078 assert!(matches!(
3079 scene.add_mesh(tri(), bad),
3080 Err(SceneError::Bvh(_))
3081 ));
3082 assert!(scene.ids().next().is_none());
3083 assert!(matches!(
3085 MeshBuild::new(tri(), bad),
3086 Err(SceneError::Bvh(_))
3087 ));
3088 }
3089
3090 #[test]
3091 fn mesh_built_with_normals_in_steps_matches_add_mesh_and_set_normals() {
3092 let bits =
3097 |n: &[[f32; 3]]| -> Vec<u32> { n.iter().flatten().map(|x| x.to_bits()).collect() };
3098 let opts = MeshOptions::default();
3099 let plain_steps = {
3100 let mut build = MeshBuild::new(sheet(30), opts).unwrap();
3101 let mut steps = 0;
3102 while !build.step(97).unwrap() {
3103 steps += 1;
3104 }
3105 steps
3106 };
3107 for budget in [Some(1), Some(97), Some(5000), Some(usize::MAX), None] {
3109 let mut a = Scene::new(SceneOptions::default());
3110 let mut b = Scene::new(SceneOptions::default());
3111 let added = a.add_mesh(sheet(30), opts).unwrap();
3112 a.set_normals(added, true).unwrap();
3113 let mut build = MeshBuild::new(sheet(30), opts).unwrap();
3114 build.set_normals(true);
3115 if let Some(budget) = budget {
3116 let mut steps = 0;
3117 while !build.step(budget).unwrap() {
3118 steps += 1;
3119 }
3120 assert!(build.is_done());
3121 if budget == 97 {
3122 assert!(
3123 steps > plain_steps,
3124 "{steps} vs {plain_steps}: normals take steps"
3125 );
3126 }
3127 }
3128 let built = b.add_mesh_built(build).unwrap();
3129 assert_eq!(added, built);
3130 assert_eq!(a.take_changes(), b.take_changes(), "{budget:?}");
3131 assert_eq!(
3132 bits(a.normals(added).unwrap().unwrap()),
3133 bits(b.normals(built).unwrap().unwrap()),
3134 "{budget:?}"
3135 );
3136 b.set_normals(built, true).unwrap();
3137 assert!(b.take_changes().is_empty(), "already on");
3138 for s in [&mut a, &mut b] {
3140 s.edit(added, |tx| {
3141 tx.remove_triangles(&[3])?;
3142 tx.set_positions(&[40], &[[0.5, 0.5, 0.4]])
3143 })
3144 .unwrap();
3145 }
3146 assert_eq!(a.take_changes(), b.take_changes());
3147 assert_eq!(
3148 bits(a.normals(added).unwrap().unwrap()),
3149 bits(b.normals(built).unwrap().unwrap())
3150 );
3151 }
3152 let mut b = Scene::new(SceneOptions::default());
3154 let mut build = MeshBuild::new(sheet(4), opts).unwrap();
3155 build.set_normals(true);
3156 build.set_normals(false);
3157 let id = b.add_mesh_built(build).unwrap();
3158 assert_eq!(b.normals(id).unwrap(), None);
3159 }
3160}