fast_mesh_scene/lib.rs
1//! Scenes of several editable meshes, built on [`fast_mesh_store`],
2//! [`fast_mesh_bvh`] and [`fast_mesh_query`].
3//!
4//! A [`Scene`] owns meshes, each with a BVH, an [`UpdateMode`] and a
5//! [`Placement`] (a rotation, a per-axis scale and a translation into the
6//! world). Meshes are addressed by generational [`MeshId`]s: once a mesh is
7//! removed, its id is rejected with [`SceneError::UnknownMesh`] for good.
8//!
9//! - Registry: [`Scene::add_mesh`], [`Scene::remove_mesh`], [`Scene::mesh`]
10//! and [`Scene::ids`] (in index order).
11//! - Placements: [`Scene::placement`] and [`Scene::set_placement`]. A
12//! placement is validated (a proper rotation, a finite positive scale)
13//! and stored exactly as given. World queries, fields and sections all
14//! follow the scale; pair queries run on copies baked into one mesh's
15//! local space (or into the world) when a scale is involved.
16//! - Editing: [`Scene::edit`] runs a store transaction on one mesh and
17//! records its patch. All-or-nothing: a failed edit changes nothing.
18//! The closure may fail with any error that converts into
19//! [`SceneError`], so repair operations from [`ops`] (the re-exported
20//! `fast-mesh-ops`) run directly:
21//! `scene.edit(id, |tx| ops::fill_holes(tx, &options))`.
22//! - Joining: [`Scene::join`] appends one mesh's geometry into another and
23//! bridges a loop on each, as one undo step, then removes the source mesh.
24//! - Cutting: [`Scene::cut_by_plane`] splits a mesh with a world plane,
25//! capping both openings flat by default, and adds the removed side as a
26//! new mesh with the same placement, as one undo step.
27//! - Booleans: [`Scene::boolean`] unions, subtracts or intersects mesh B
28//! into mesh A in the world; the result replaces A with A's placement,
29//! as one undo step.
30//! - Registration: [`Scene::register`] rigidly aligns one mesh to another by
31//! trimmed point-to-plane ICP from their current placements, and sets the
32//! moving mesh's placement as one undo step when the result is good.
33//! - History: one undo history across all meshes, in steps.
34//! [`Scene::begin_step`] / [`Scene::end_step`] group edits and placement
35//! changes (otherwise each is its own step); [`Scene::undo`],
36//! [`Scene::redo`] and [`Scene::cancel_step`] are all-or-nothing per step.
37//! [`SceneOptions::history_budget`] evicts the oldest steps.
38//! - BVH state: each mesh's [`UpdateMode`] says when its BVH follows the
39//! mesh; [`Scene::set_mode`], [`Scene::update`], [`Scene::flush`] and
40//! [`Scene::is_current`].
41//! - Change reports: [`Scene::take_changes`] drains one [`MeshChanges`] per
42//! affected mesh. Further consumers each get their own copy of every
43//! report: [`Scene::subscribe`], [`Scene::take_changes_for`] and
44//! [`Scene::unsubscribe`].
45//! - UVs: a mesh added with [`Mesh::add_uvs`](fast_mesh_store::Mesh::add_uvs)
46//! keeps them through edits, undo and redo. Every operation preserves or
47//! undoably drops them; see
48//! [`docs/uv-channel.md`](https://github.com/YoonDongGeun/fast-mesh-wasm/blob/main/docs/uv-channel.md).
49//! - Maintenance: [`Scene::add_channel`], [`Scene::remove_channel`],
50//! [`Scene::derived_channel_mut`] (all three reported, and the `field:`
51//! prefix reserved) and [`Scene::compact`].
52//! - Local space: [`Scene::bvh`] (current BVHs only),
53//! [`Scene::relative_transform`], [`Scene::world_to_local`] and
54//! [`Scene::local_to_world`].
55//! - World queries, in world `f64` coordinates: [`Scene::raycast`],
56//! [`Scene::closest_point`] and [`Scene::closest_point_on`], and between
57//! two meshes [`Scene::intersects`], [`Scene::mesh_distance`] and
58//! [`Scene::triangles_near`]. Each maps into mesh-local space, runs the
59//! Phase 3 query and maps the result back; bounds are rounded outward to
60//! `f32` and results filtered against the exact bound. Queries over all
61//! meshes update every Lazy BVH and fail with [`SceneError::StaleBvh`] on
62//! a stale Manual one; queries naming meshes touch only those.
63//! - Contacts: [`Scene::find_contacts`] finds the mesh pairs within a margin
64//! (broadphase over world boxes, then Phase 3b per pair), optionally
65//! restricted by a [`ContactFilter`].
66//! - Distance fields: [`Scene::add_distance_field`] registers a signed
67//! distance field ([`DistanceField`]) from one mesh's vertices to another
68//! mesh, stored in a derived channel `field:<name>` and kept up to date
69//! incrementally under the [`UpdateMode`] of the mesh it is on
70//! ([`Scene::update_fields`], [`Scene::flush`]). Read with
71//! [`Scene::field_values`] and [`Scene::field_status`]; list a mesh's with
72//! [`Scene::fields_on`]; change `max_distance` or the sign mode with
73//! [`Scene::reconfigure_field`]; remove with [`Scene::remove_field`] (or
74//! with either mesh).
75//! - Colours: [`Scene::set_coloring`] colours a mesh from one of its fields
76//! with a [`ColorRule`]; [`Scene::coloring`] returns the colouring,
77//! [`Scene::colors`] one RGBA8 per vertex slot, and recoloured vertices
78//! are reported in [`MeshChanges::colors_dirty`].
79//! - Normals: [`Scene::set_normals`] turns a mesh's smooth vertex normals
80//! on; [`Scene::normals`] returns one mesh-local normal per vertex slot,
81//! kept up to date incrementally under the mesh's [`UpdateMode`], and
82//! recomputed vertices are reported in [`MeshChanges::normals_dirty`].
83//! - Sections: [`Scene::add_section`] cuts meshes with a world [`Plane`]
84//! ([`SectionDesc`]) into contours in world and plane `(u, v)`
85//! coordinates, with length, signed area and an optional fill
86//! ([`SectionResult`]), kept up to date under each mesh's [`UpdateMode`]
87//! ([`Scene::update_sections`], [`Scene::flush`]). Read with
88//! [`Scene::section`], [`Scene::section_status`] and
89//! [`Scene::section_gap`]; changes are reported in
90//! [`MeshChanges::sections_changed`].
91
92mod baked;
93mod boolean;
94mod contacts;
95mod cut;
96mod error;
97mod fields;
98mod history;
99mod id;
100mod join;
101mod normals;
102mod placement;
103mod query;
104mod register;
105mod report;
106mod scene;
107mod sculpt;
108mod sections;
109#[cfg(test)]
110mod uv_tests;
111
112pub use boolean::{BooleanOp, BooleanReport};
113pub use contacts::{Contact, ContactFilter};
114pub use cut::{CutOptions, CutReport};
115pub use error::{Result, SceneError};
116pub use fast_mesh_fields::{
117 ColorRule, Colormap, FieldsError, OutOfRange, SignMode, SignStatus, color_of,
118};
119pub use fast_mesh_ops as ops;
120pub use fast_mesh_query::{Fill, Plane};
121pub use fields::{
122 Coloring, CurvatureField, DistanceField, FieldBudget, FieldStatus, StepState, ThicknessField,
123};
124pub use id::MeshId;
125pub use join::{JoinOptions, JoinReport};
126pub use placement::Placement;
127pub use query::{
128 SceneClosestHit, SceneClosestOptions, SceneMeshDistance, SceneRayHit, SceneRayOptions,
129};
130pub use register::{DEFAULT_MAX_RMSE_FRACTION, NotApplied, RegisterOptions, RegisterReport};
131pub use report::SectionId;
132pub use report::{FieldId, MeshChanges, SubscriberId};
133pub use scene::{MeshBuild, MeshOptions, Scene, SceneOptions, UpdateMode};
134pub use sculpt::{Dab, DabReport};
135pub use sections::{Gap, SectionContour, SectionDesc, SectionResult, SectionStatus};