Skip to main content

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};