pub struct Scene { /* private fields */ }Expand description
Several meshes, each with a BVH and a placement in the world.
Implementations§
Source§impl Scene
impl Scene
Sourcepub fn boolean(
&mut self,
a: MeshId,
b: MeshId,
op: BooleanOp,
) -> Result<BooleanReport>
pub fn boolean( &mut self, a: MeshId, b: MeshId, op: BooleanOp, ) -> Result<BooleanReport>
Combines mesh B into mesh A: union, subtract or intersect as placed in the world. The result replaces A with A’s placement, so the world shape is the boolean of the world shapes; B is unchanged. Closed manifold inputs give a closed result; touches leave pinch vertices.
The combination runs as one edit of A, so it undoes in one step.
Combining a mesh with itself is a no-op for union and intersect
(nothing is recorded), and clears it for subtract. Only positions
and triangles cross over: new vertices take channel defaults, and A’s
UV channel is dropped (BooleanReport::uvs_dropped). Since UVs do not
survive, a mesh with UVs is read with exactly coincident vertices
merged, so seams do not make a closed surface count as open; every
input check below applies to the merged geometry. B is unchanged, and
undo restores A’s split vertices.
§Errors
[SceneError::UnknownMesh] for a stale id;
[SceneError::InvalidInput] when an input is not closed, manifold,
consistently wound or free of degenerate, duplicate and
self-intersecting triangles, or when a mapped position leaves f32
range; [SceneError::Ops], [SceneError::Query],
[SceneError::Store] or [SceneError::StaleBvh] from the plan, the
bakes and the edit. A failed boolean changes nothing. A stale Manual
BVH fails the query with [SceneError::StaleBvh], like the pair
queries.
Source§impl Scene
impl Scene
Sourcepub fn find_contacts(
&mut self,
margin: f64,
filter: &ContactFilter,
out: &mut Vec<Contact>,
) -> Result<usize>
pub fn find_contacts( &mut self, margin: f64, filter: &ContactFilter, out: &mut Vec<Contact>, ) -> Result<usize>
Appends a Contact for every mesh pair (of filter, or of the whole
scene) whose surfaces are within margin of each other as placed in
the world, sorted by (a, b), and returns how many were appended.
Elements already in out stay in front.
The broadphase keeps the pairs whose world boxes (BVH root boxes
placed by the rigid transforms) are within margin, padded so that it
never drops a pair Phase 3b would report. For each, in A’s space:
intersecting comes from fast_mesh_query::intersects; distance
is 0 when intersecting, else from fast_mesh_query::mesh_distance
with margin rounded up to f32, and a pair whose distance exceeds
the exact margin is not reported; the triangle lists come from
fast_mesh_query::triangles_near with the rounded-up margin (see
Scene::triangles_near).
With filter.pairs, each pair may be given either way round and more
than once; only the listed meshes’ BVHs are brought up to date.
Without, every Lazy BVH is (§15.4).
§Errors
SceneError::InvalidInput for a negative or NaN margin or a pair
naming one mesh twice; SceneError::UnknownMesh for a stale id in
the filter; then a BVH or memory error from a Lazy update,
SceneError::StaleBvh for the lowest stale Manual mesh involved, or
a memory error while collecting. On any error out keeps its length.
Source§impl Scene
impl Scene
Sourcepub fn cut_by_plane(
&mut self,
id: MeshId,
options: &CutOptions,
) -> Result<CutReport>
pub fn cut_by_plane( &mut self, id: MeshId, options: &CutOptions, ) -> Result<CutReport>
Cuts the mesh with a world plane: the + side
(signed_distance >= 0) stays on the mesh and the - side is added
as a new mesh, both with the mesh’s placement, so the world shape is
kept. With options.cap (the usual case) both openings are closed
with flat, unfaired patches; without it both parts keep the open rim.
Cutting a closed mesh with cap yields two closed meshes. On a mesh
with UVs, closed means closed by exact position, so seams count as
closed. A rim that runs into a real boundary stays open; on a mesh
without UVs, split vertices are such a boundary, so weld them first.
The cut runs as one edit of the mesh, so it undoes in one step; the
added mesh is permanent, like the removed source of Scene::join.
Only positions and triangles cross over: the added mesh has no
normals, colouring, fields or section entries, and new vertices take
channel defaults (crossing vertices on the kept side interpolate
their parents). UVs carry over to both sides, interpolated at the
crossing vertices and across the caps.
§Errors
[SceneError::UnknownMesh] for a stale id;
[SceneError::InvalidInput] when the plane does not cut the mesh, or
a rim cannot be capped; [SceneError::Ops] or [SceneError::Store]
from the cut or the add. A failed cut changes nothing. If adding the
removed side fails (out of memory), the cut of the original stays
recorded and the added mesh is missing.
Source§impl Scene
impl Scene
Sourcepub fn add_distance_field(&mut self, desc: DistanceField) -> Result<FieldId>
pub fn add_distance_field(&mut self, desc: DistanceField) -> Result<FieldId>
Registers a signed distance field on mesh desc.on, measured to the
meshes desc.to, and returns its id. Its values go into a derived
channel field:<name> on desc.on, readable with
Scene::field_values or through Scene::mesh; they are not
undoable. With several targets, a vertex’s value is the smallest over
them, and Scene::field_nearest tells which target it came from.
The field follows the UpdateMode of desc.on: an Eager field is
computed right away and after every edit, placement change, undo,
redo or cancel touching desc.on or a target; a Lazy one by
Scene::flush or Scene::update_fields; a Manual one only by
Scene::update_fields. Until then its values are NaN.
The targets’ BVHs are brought up to date under the query rules (a
Lazy one is updated) and their sign data built here, so that
Scene::field_status can report their topology at once.
A position-only edit of a target mesh refits its pseudonormal sign
data around the dirty vertices; any other edit rebuilds it over the
whole mesh (O(n), about 150 ms at 1M triangles, more after a topology
edit, which drops the cached adjacency). Placement changes and edits
of desc.on do not rebuild it.
§Errors
SceneError::UnknownMesh; SceneError::InvalidInput when to is
empty, holds on or a mesh twice, max_distance is negative or NaN,
or on already has a field of that name; SceneError::StaleBvh
when a target is a stale Manual mesh; a BVH, field or memory error.
The scene is unchanged on error.
Sourcepub fn add_distance_field_deferred(
&mut self,
desc: DistanceField,
) -> Result<FieldId>
pub fn add_distance_field_deferred( &mut self, desc: DistanceField, ) -> Result<FieldId>
Registers a field as Scene::add_distance_field does, but computes
nothing yet: no sign data are built and no BVH is brought up to date,
whatever the mode of desc.on. The field is due until an update
computes it: Scene::field_step (an Eager field),
Scene::field_step_field, Scene::update_fields,
Scene::flush (Eager and Lazy) or, unless deferred, the next
change to one of its meshes (Eager). Until then its values are NaN
and Scene::field_status reports placeholder sign data (see
Scene::field_target_status). Computed in steps, its values,
colours and reports are the same, bit for bit, as from
Scene::add_distance_field.
§Errors
SceneError::UnknownMesh; SceneError::InvalidInput as for
Scene::add_distance_field; a memory error. The scene is unchanged
on error. Errors of the BVHs and sign data come from the update that
computes the field.
Sourcepub fn withdraw_field(&mut self, id: FieldId) -> Result<bool>
pub fn withdraw_field(&mut self, id: FieldId) -> Result<bool>
Removes a field that has never been computed, as if it had never
been added: unlike Scene::remove_field nothing is reported.
Returns false, doing nothing, when the field was computed (by any
update) or colours its mesh; Scene::remove_field then applies.
§Errors
SceneError::UnknownField for an unknown or removed field.
Sourcepub fn add_thickness_field(&mut self, desc: ThicknessField) -> Result<FieldId>
pub fn add_thickness_field(&mut self, desc: ThicknessField) -> Result<FieldId>
Registers a per-vertex wall-thickness field on mesh desc.on, and
returns its id. Its values go into a derived channel field:<name> on
desc.on, readable with Scene::field_values or through
Scene::mesh; they are not undoable.
The field follows the UpdateMode of desc.on like a distance
field: an Eager one is computed right away and after every edit,
placement change, undo, redo or cancel touching desc.on; a Lazy one
by Scene::flush or Scene::update_fields; a Manual one only by
Scene::update_fields. Until then its values are NaN. Every update
recomputes every vertex in full (a thickness has no targets to narrow
it down to).
A non-uniformly scaled placement is baked into a world-frame copy for the update, so the values are world distances; a uniform scale multiplies the local values, and a rigid placement changes nothing.
§Errors
SceneError::UnknownMesh; SceneError::InvalidInput when
max_distance is negative or NaN, or on already has a field of that
name; SceneError::StaleBvh when the mesh is a stale Manual mesh; a
BVH, field or memory error. The scene is unchanged on error.
Sourcepub fn add_thickness_field_deferred(
&mut self,
desc: ThicknessField,
) -> Result<FieldId>
pub fn add_thickness_field_deferred( &mut self, desc: ThicknessField, ) -> Result<FieldId>
Scene::add_thickness_field computing nothing yet: the field is due
until an update computes it (Scene::field_step (an Eager field),
Scene::field_step_field, Scene::update_fields or
Scene::flush, unless deferred, the next change to its mesh (an
Eager field)). Until then its values are NaN.
§Errors
SceneError::UnknownMesh; SceneError::InvalidInput as for
Scene::add_thickness_field; a memory error. The scene is unchanged
on error. Errors of the BVH come from the update that computes the
field.
Sourcepub fn add_curvature_field(&mut self, desc: CurvatureField) -> Result<FieldId>
pub fn add_curvature_field(&mut self, desc: CurvatureField) -> Result<FieldId>
Registers a per-vertex curvature field on mesh desc.on, and returns
its id. Its values go into a derived channel field:<name> on
desc.on, readable with Scene::field_values or through
Scene::mesh; they are not undoable.
The field follows the UpdateMode of desc.on like a distance
field: an Eager one is computed right away and after every edit,
placement change, undo, redo or cancel touching desc.on; a Lazy one
by Scene::flush or Scene::update_fields; a Manual one only by
Scene::update_fields. Until then its values are NaN. Every update
recomputes every vertex in full (a curvature has no targets to narrow
it down to).
A non-uniformly scaled placement is baked into a world-frame copy for
the update, so the values are world curvatures; a uniform scale s
divides the local values by s, and a rigid placement changes
nothing.
§Errors
SceneError::UnknownMesh; SceneError::InvalidInput when on
already has a field of that name; SceneError::StaleBvh when the
mesh is a stale Manual mesh; a BVH, field or memory error. The scene
is unchanged on error.
Sourcepub fn add_curvature_field_deferred(
&mut self,
desc: CurvatureField,
) -> Result<FieldId>
pub fn add_curvature_field_deferred( &mut self, desc: CurvatureField, ) -> Result<FieldId>
Scene::add_curvature_field computing nothing yet: the field is due
until an update computes it (Scene::field_step (an Eager field),
Scene::field_step_field, Scene::update_fields or
Scene::flush, unless deferred, the next change to its mesh (an
Eager field)). Until then its values are NaN.
§Errors
SceneError::UnknownMesh; SceneError::InvalidInput as for
Scene::add_curvature_field; a memory error. The scene is unchanged
on error. Errors of the BVH come from the update that computes the
field.
Sourcepub fn remove_field(&mut self, id: FieldId) -> Result<()>
pub fn remove_field(&mut self, id: FieldId) -> Result<()>
Removes a field: its channel leaves its mesh, a colouring by it is
removed (reported as colors_dirty: None), and the removal is
reported in the mesh’s MeshChanges::fields_changed.
The id is rejected from then on.
§Errors
SceneError::UnknownField for an unknown or removed field.
Sourcepub fn update_fields(&mut self) -> Result<()>
pub fn update_fields(&mut self) -> Result<()>
Brings every field that is not current up to date, whatever the mode
of its mesh, bringing the BVHs it needs up to date under the query
rules (Lazy ones are updated). Renderers call this (or
Scene::flush), then read any number of fields and colours.
§Errors
The first error, for example SceneError::StaleBvh when a BVH a
field needs is a stale Manual one: B’s always, A’s when the field
must look for A’s triangles near B (after a placement change or an
edit of B). Such a field makes every call (and every
Scene::flush) return StaleBvh until that BVH is brought up to
date with Scene::update. Every field is still attempted; those
that failed stay stale and keep their pending changes.
Sourcepub fn field_values(&self, id: FieldId) -> Result<&[f32]>
pub fn field_values(&self, id: FieldId) -> Result<&[f32]>
The field’s values, one per vertex slot of its mesh, as of its last
update (see Scene::field_status): signed distances, +∞ for far,
NaN for dead or unused vertices. A thickness field holds wall
thicknesses instead (+∞ past max_distance, NaN where the rays
escape), and a curvature field signed mean curvatures in 1/world-unit
(NaN for dead or unused vertices). Never updates.
§Errors
SceneError::UnknownField for an unknown or removed field.
Sourcepub fn field_nearest(&self, id: FieldId) -> Result<&[u32]>
pub fn field_nearest(&self, id: FieldId) -> Result<&[u32]>
Per vertex slot of the field’s mesh, as of its last update: the index
in Scene::field_targets of the target its value came from (the
lowest on a tie), or u32::MAX for none (a +∞ or NaN value, or a
slot not computed yet). It can be shorter than the mesh’s slots
(slots added since the last update): those slots have none.
Thickness and curvature fields have no targets and report none.
Never updates.
After a target mesh is removed, and until the field’s next update (at once for an Eager field, unless deferred), the vertices whose value came from it have none here while their value stays finite, and the later indices are shifted down to the remaining targets.
§Errors
SceneError::UnknownField for an unknown or removed field.
Sourcepub fn field_targets(&self, id: FieldId) -> Result<&[MeshId]>
pub fn field_targets(&self, id: FieldId) -> Result<&[MeshId]>
The field’s target meshes, in index order. Removing a target mesh removes it from here, shifting the later ones down. Thickness and curvature fields have no targets.
§Errors
SceneError::UnknownField for an unknown or removed field.
Sourcepub fn field_target_status(&self, id: FieldId) -> Result<Vec<SignStatus>>
pub fn field_target_status(&self, id: FieldId) -> Result<Vec<SignStatus>>
What the latest sign data build found out about each of the field’s targets, in index order. Thickness and curvature fields have no targets. Never updates.
§Errors
SceneError::UnknownField for an unknown or removed field.
A target whose sign data were never built (a field added with
Scene::add_distance_field_deferred, not computed yet) reports a
placeholder: the requested mode (Auto as
SignMode::Pseudonormal), not closed, not consistently oriented,
and no counts.
Sourcepub fn field_status(&self, id: FieldId) -> Result<FieldStatus>
pub fn field_status(&self, id: FieldId) -> Result<FieldStatus>
Whether the field is current, and what the latest sign data builds
found out about its target meshes, together (see
FieldStatus::sign). Thickness and curvature fields have no sign
data and report the placeholder (neither closed nor consistently
oriented). Never updates.
§Errors
SceneError::UnknownField for an unknown or removed field.
Sourcepub fn set_coloring(
&mut self,
mesh: MeshId,
coloring: Option<Coloring>,
) -> Result<()>
pub fn set_coloring( &mut self, mesh: MeshId, coloring: Option<Coloring>, ) -> Result<()>
Colours mesh from one of its fields, or stops colouring it with
None. Every vertex is recoloured from the field’s current values,
and reported as colors_dirty: None. Field updates then recolour the
vertices whose values changed and report them. Colours are not
undoable.
§Errors
SceneError::UnknownMesh; SceneError::UnknownField;
SceneError::InvalidInput when the field is not on mesh or the
rule is invalid (see ColorRule::validate). The scene is unchanged
on error.
Sourcepub fn colors(&self, mesh: MeshId) -> Result<Option<&[[u8; 4]]>>
pub fn colors(&self, mesh: MeshId) -> Result<Option<&[[u8; 4]]>>
The mesh’s colours, or None when the mesh has no colouring. Never
updates.
The slice always holds exactly one RGBA8 per vertex slot
(colors(mesh).len() == mesh.vertex_slots()), so it can be indexed
by vertex id at any time. The colours follow the field’s values as of
its last update; slots added since are coloured from the field’s
channel (NaN, so ColorRule::nan) until the field is updated.
§Errors
SceneError::UnknownMesh for a stale id.
Sourcepub fn color_values(&self, mesh: MeshId) -> Result<Option<&[f32]>>
pub fn color_values(&self, mesh: MeshId) -> Result<Option<&[f32]>>
The values the mesh’s colours are made from, or None when the mesh
has no colouring. Never updates.
A view of the colouring field’s channel, not a copy: the same slice as
Scene::field_values of that field, one f32 per vertex slot. It
changes only at vertices reported in colors_dirty, so a renderer can
mirror it with the colours’ dirty ranges and map values to colours per
fragment (color_of at a vertex gives that vertex’s colour).
§Errors
SceneError::UnknownMesh for a stale id.
Sourcepub fn coloring(&self, mesh: MeshId) -> Result<Option<&Coloring>>
pub fn coloring(&self, mesh: MeshId) -> Result<Option<&Coloring>>
The mesh’s colouring, or None when the mesh has no colouring. Never
updates.
§Errors
SceneError::UnknownMesh for a stale id.
Sourcepub fn fields_on(&self, mesh: MeshId) -> Result<Vec<FieldId>>
pub fn fields_on(&self, mesh: MeshId) -> Result<Vec<FieldId>>
The ids of the fields on mesh, in the order they were added. Never
updates.
§Errors
SceneError::UnknownMesh for a stale id.
Sourcepub fn reconfigure_field(
&mut self,
id: FieldId,
max_distance: f64,
sign: SignMode,
) -> Result<()>
pub fn reconfigure_field( &mut self, id: FieldId, max_distance: f64, sign: SignMode, ) -> Result<()>
Changes a field’s max_distance and sign mode, keeping its id, its
name, its meshes and any colouring by it. The field is recomputed in
full on its next update (at once for an Eager field); until then its
values are stale and Scene::field_status reports it as not
current, with placeholder sign data when the sign mode changed. A
thickness field has no sign mode (sign is ignored for it), and a
curvature field has neither (max_distance is ignored for it too:
the call still marks it for recompute).
§Errors
SceneError::UnknownField for an unknown or removed field;
SceneError::InvalidInput when max_distance is negative or NaN.
The scene is unchanged on error.
Sourcepub fn field_id(&self, raw: u32) -> Option<FieldId>
pub fn field_id(&self, raw: u32) -> Option<FieldId>
The id of the registered field with this FieldId::raw value, or
None when there is none (never added, or removed).
Sourcepub fn set_defer_fields(&mut self, on: bool)
pub fn set_defer_fields(&mut self, on: bool)
Defers Eager field updates: with on, the edits, placement changes,
undos, redos, cancels and Scene::update calls that would update
the Eager fields involving a mesh leave them due instead, for
Scene::field_step (or Scene::update_fields or
Scene::flush) to bring up to date. Registering a field on an
Eager mesh still computes it at once. Leaves an open step unit open.
Turning it off does not bring fields that are already due up to
date: they wait for the next change involving their meshes, or for
Scene::field_step, Scene::update_fields or Scene::flush.
Sourcepub fn set_field_interaction(&mut self, points: Option<usize>) -> Result<()>
pub fn set_field_interaction(&mut self, points: Option<usize>) -> Result<()>
Starts (Some(points)) or ends (None) an interaction: a gesture
that changes a placement or a mesh many times a second, during which
a distance field too large to recompute per update stays live near
the contact and is made exact when the gesture ends.
During an interaction, a field with more finite values than points
updates at most points vertices closest to the targets (no pair
search: a distance changes no faster than the motion, so its last value
and how far the meshes have moved since say which can be close), the
vertices around an edit, and a sweep of an eighth of points further
vertices. The others keep their values, so that nothing turns far or
loses its colour; those values are out of date by at most how far the
meshes moved since they were computed (for an edit of a target, by how
far it moved its surface, away from the edit’s box), and
Scene::field_status does not report it. The band of the closest
vertices follows the work from the counts alone, so results are the
same with parallel on or off, for any thread count. A field of at
most points finite values updates exactly as usual.
Ending the interaction recomputes every vertex of the fields it left
out of date, at once for Eager meshes unless fields are deferred (see
Scene::set_defer_fields and Scene::field_step); the values,
colours and reports are then those of an exact update. Starting one
again before that keeps them on the tier, and a gesture that changed
nothing leaves nothing to recompute. Drops an open step unit when
the setting changes.
§Errors
SceneError::InvalidInput when points is Some(0). The scene
is unchanged on error.
Sourcepub fn field_interaction(&self) -> Option<usize>
pub fn field_interaction(&self) -> Option<usize>
The budget of the interaction under way (see
Scene::set_field_interaction), if any.
Sourcepub fn field_step(&mut self, budget: FieldBudget) -> Result<StepState>
pub fn field_step(&mut self, budget: FieldBudget) -> Result<StepState>
Computes part of the Eager fields that are due, so that a long update can be spread over several calls (a Worker yields between them).
The first call opens a unit: it takes every due field on an Eager
mesh (as an Eager update would) and brings the BVHs each reads up to
date. Every call, the first included, then advances the unit’s
fields in field order, writing nothing: for each, the build of its
targets’ sign data when they are not current (about budget times
32 elements of the build per call), its near search (whole parts,
about budget times 16 triangle pairs per call), the choice of the
vertices it recomputes (see the module docs), and the values of up
to budget of those vertices per call. A call that builds sign data
or searches does only that. The call that finishes the last field
applies every field of the unit together and returns
StepState::Done: values, colours and reports are then the same,
bit for bit, as from Scene::update_fields at the state the unit
opened at.
An open unit, including one opened by Scene::field_step_field,
is continued. Any other &mut self call on the scene drops it first
(see Scene::abandon_field_step), except
Scene::abandon_field_step and Scene::set_defer_fields.
A unit leaves a trace when it is then abandoned: the BVHs it brought up to date stay refitted, and the sign data it finished building stay with their fields, as after any query that needs them. A sign data build it left unfinished is kept with its field, and a later unit resumes it while its mesh and BVH are unchanged. No value, colour, report or pending change depends on whether that happened.
§Errors
Errors are isolated per field, as in Scene::update_fields: a
field that fails, when the unit opens (for example
SceneError::StaleBvh for a stale Manual mesh) or while it is
advanced, is dropped from the unit and stays stale and due, as after
a failed Eager update. The other fields go on, and the call that
applies them returns the first error in field order instead of
StepState::Done. When no due field can be opened, the first
error is returned and no unit is opened.
Sourcepub fn field_step_field(
&mut self,
id: FieldId,
budget: FieldBudget,
) -> Result<StepState>
pub fn field_step_field( &mut self, id: FieldId, budget: FieldBudget, ) -> Result<StepState>
Scene::field_step for field id alone, whatever its mesh’s
mode: opens a unit over it when it is not current and no unit for it
is open (dropping another open unit), or continues its open unit.
Returns StepState::Idle when the field is current. The call that
finishes it applies it, with the same values, colours and reports as
Scene::update_fields would give it. A thickness or curvature field
holds no incremental state: stepping it computes it in full at once.
§Errors
SceneError::UnknownField for an unknown or removed field; then
as for Scene::field_step.
Sourcepub fn abandon_field_step(&mut self)
pub fn abandon_field_step(&mut self)
Drops the open step unit, if any: nothing it computed is written or
reported, and its fields stay due. Does nothing when no unit is
open. What the unit brought up to date (BVHs, finished sign data)
stays so, and an unfinished sign data build is kept; see
Scene::field_step.
Sourcepub fn field_step_pending(&self) -> bool
pub fn field_step_pending(&self) -> bool
Whether a step unit is open (see Scene::field_step).
Sourcepub fn field_step_meshes(&self) -> Vec<MeshId>
pub fn field_step_meshes(&self) -> Vec<MeshId>
The meshes the fields of the open step unit are on and measured to, each once, in field order; empty when no unit is open. A change to any of them makes the unit stale.
Source§impl Scene
impl Scene
Sourcepub fn join(
&mut self,
a: MeshId,
b: MeshId,
options: &JoinOptions,
) -> Result<JoinReport>
pub fn join( &mut self, a: MeshId, b: MeshId, options: &JoinOptions, ) -> Result<JoinReport>
Joins the source mesh into the target: copies the source’s alive
positions (mapped into the target’s local frame, so the world shape
is kept) and triangles into the target, bridges loop_a to the
copied loop_b, and removes the source mesh. The copy and the bridge
run in one edit, so they undo together; the removal is permanent,
like Scene::remove_mesh.
Only positions and triangles cross over: the source’s channels are
dropped, and the target’s channels take their defaults on the new
vertices. UVs are the exception: when both meshes have them they carry
over, and when only one has them the result has none
(JoinReport::uvs_dropped).
§Errors
SceneError::UnknownMesh for a stale id;
SceneError::InvalidInput when the two ids are one mesh;
SceneError::Ops with OpsError::StaleLoops for a loop that is
not there, or OpsError::InvalidInput when the loops cannot bridge
(unclean, over max_edges, winding the same way). A failed join
changes nothing: both meshes are left as they were. If removing the
source fails (out of memory), the joined geometry stays recorded and
the source mesh with it.
Source§impl Scene
impl Scene
Sourcepub fn set_normals(&mut self, id: MeshId, on: bool) -> Result<()>
pub fn set_normals(&mut self, id: MeshId, on: bool) -> Result<()>
Turns the mesh’s vertex normals on or off (off by default). Turning
them on computes them right away, whatever the mesh’s
UpdateMode; either switch is reported as
normals_dirty: None. Setting the current state again does nothing.
While on, the normals follow the mesh like its BVH: an Eager mesh’s
right after every edit, undo, redo and cancel, a Lazy one’s on
Scene::flush or Scene::update, a Manual one’s on
Scene::update only. A compaction recomputes them in full right
away. Placement changes leave them alone: they are mesh-local.
Memory: besides 12 bytes of normal per vertex slot, a snapshot of the triangles (12 bytes per triangle slot) is kept while normals are on, so the old vertices of removed and rewritten triangles are known.
§Errors
SceneError::UnknownMesh, or SceneError::Store when there is
no memory for them. The scene is unchanged on error.
Sourcepub fn normals(&self, id: MeshId) -> Result<Option<&[[f32; 3]]>>
pub fn normals(&self, id: MeshId) -> Result<Option<&[[f32; 3]]>>
The mesh’s vertex normals in mesh-local space, one per vertex slot,
or None when normals are off. A normal is the normalised sum of the
area-weighted normals of the alive triangles using the vertex; a
vertex used by none (or only by degenerate ones), dead slots
included, reads [0, 0, 0].
The normals of a Lazy or Manual mesh are those of its last update
(new vertex slots read zero until then). The slice may differ in
length from mesh.vertex_slots() until the next successful update:
shorter if memory ran out while following an edit, or longer if the
recomputation after a compaction failed.
§Errors
SceneError::UnknownMesh for a stale id.
Source§impl Scene
impl Scene
Sourcepub fn raycast(
&mut self,
origin: [f64; 3],
dir: [f64; 3],
opts: &SceneRayOptions,
) -> Result<Option<SceneRayHit>>
pub fn raycast( &mut self, origin: [f64; 3], dir: [f64; 3], opts: &SceneRayOptions, ) -> Result<Option<SceneRayHit>>
The nearest hit of a world ray over every mesh, with
opts.min_t <= t <= opts.max_t in world distance. Equal t goes to
the lower MeshId; within a mesh, Phase 3’s rule (smallest
triangle id) applies.
dir is normalised in f64, so t is a world distance. For each
mesh not culled by its world box, the ray is mapped into the mesh’s
local space (the origin by the placement inverse, the direction by
its linear inverse, in f64, then rounded to f32) and Phase 3’s
fast_mesh_query::raycast runs there, with the bounds rounded
outward to f32. The affine map keeps the ray parameter, so the
local t is the world t up to that rounding; hits are kept only
when it lies within the exact f64 bounds, and a hit dropped just
below min_t does not hide one beyond it.
Every Lazy BVH is brought up to date first (§15.4).
§Errors
SceneError::InvalidInput for a non-finite origin, a zero or
non-finite direction, NaN bounds or min_t > max_t; then a BVH or
memory error from a Lazy update, or SceneError::StaleBvh for the
lowest stale Manual mesh; then SceneError::InvalidInput for an
origin out of f32 range in some mesh’s local space, or a memory
error.
Sourcepub fn closest_point(
&mut self,
p: [f64; 3],
opts: &SceneClosestOptions,
) -> Result<Option<SceneClosestHit>>
pub fn closest_point( &mut self, p: [f64; 3], opts: &SceneClosestOptions, ) -> Result<Option<SceneClosestHit>>
The point of the scene nearest to p, within opts.max_distance.
Equal distances go to the lower MeshId; within a mesh, Phase 3’s
rule (smallest triangle id) applies.
Meshes are visited by the distance from p to their world box and
pruned by the best world distance so far. In each mesh not culled,
p is mapped into local space (in f64, then rounded to f32) and
Phase 3’s fast_mesh_query::closest_point runs there: with a rigid
placement the local distance is the world distance; with a uniform
scale the local bound is the world bound divided by the scale and the
local distance is multiplied back; with a non-uniform scale the query
runs on a world-baked copy of the mesh (see [baked_mesh]). The
world distance must then be within the exact bound.
Every Lazy BVH is brought up to date first (§15.4).
§Errors
SceneError::InvalidInput for a non-finite p or a negative or
NaN max_distance; then a BVH or memory error from a Lazy update, or
SceneError::StaleBvh for the lowest stale Manual mesh; then
SceneError::InvalidInput for a p out of f32 range in some
mesh’s local space (or in the world, for a non-uniformly scaled
mesh), or a memory error.
Sourcepub fn closest_point_on(
&mut self,
id: MeshId,
p: [f64; 3],
opts: &SceneClosestOptions,
) -> Result<Option<SceneClosestHit>>
pub fn closest_point_on( &mut self, id: MeshId, p: [f64; 3], opts: &SceneClosestOptions, ) -> Result<Option<SceneClosestHit>>
Scene::closest_point on mesh id alone. Only that mesh’s BVH is
brought up to date (§15.4).
§Errors
SceneError::UnknownMesh for a stale id; then as for
Scene::closest_point, with SceneError::StaleBvh only when this
mesh is a stale Manual one.
Sourcepub fn bvh(&self, id: MeshId) -> Result<&Bvh>
pub fn bvh(&self, id: MeshId) -> Result<&Bvh>
The mesh’s BVH, in mesh-local f32 space, for running Phase 3
queries directly. Never updates it.
§Errors
SceneError::UnknownMesh for a stale id, or
SceneError::StaleBvh when the BVH is not current with the mesh
(see Scene::is_current); bring it up to date with
Scene::update or Scene::flush first.
Sourcepub fn relative_transform(&self, a: MeshId, b: MeshId) -> Result<Rigid>
pub fn relative_transform(&self, a: MeshId, b: MeshId) -> Result<Rigid>
The transform from mesh b’s local space to mesh a’s local space,
origins included: the one the pair queries (Scene::intersects,
Scene::mesh_distance, Scene::triangles_near) pass to Phase 3,
in the convention of Rigid. Its rotation is re-orthonormalised,
so it always passes Rigid::validate. Only for rigid pairs: with a
scaled placement on either side the relative map is affine, not
rigid (pair queries then run on baked copies instead).
§Errors
SceneError::UnknownMesh for a stale id;
SceneError::InvalidInput when either placement is scaled.
Sourcepub fn world_to_local(&self, id: MeshId, q: [f64; 3]) -> Result<[f64; 3]>
pub fn world_to_local(&self, id: MeshId, q: [f64; 3]) -> Result<[f64; 3]>
A world point in mesh id’s local coordinates, origin included:
S⁻¹ Rᵀ (q - t) - o, in f64.
§Errors
SceneError::UnknownMesh for a stale id.
Sourcepub fn local_to_world(&self, id: MeshId, p: [f64; 3]) -> Result<[f64; 3]>
pub fn local_to_world(&self, id: MeshId, p: [f64; 3]) -> Result<[f64; 3]>
A point in mesh id’s local coordinates in the world, origin
included: R (S (o + p)) + t, in f64.
§Errors
SceneError::UnknownMesh for a stale id.
Sourcepub fn intersects(&mut self, a: MeshId, b: MeshId) -> Result<bool>
pub fn intersects(&mut self, a: MeshId, b: MeshId) -> Result<bool>
Whether any triangle of mesh a intersects or touches any triangle of
mesh b, as placed in the world: Phase 3’s
fast_mesh_query::intersects with the relative transform of B’s
local space into A’s. Passing the same id twice means two coincident
copies, as in Phase 3. Only these two BVHs are brought up to date.
With a scaled placement on either side the query runs on a copy
baked into A’s local space (or into the world when A is
non-uniformly scaled; see Scene::bake_pair_inner): same result,
up to the copy’s f32 rounding.
§Errors
SceneError::UnknownMesh; then a BVH or memory error from a Lazy
update, or SceneError::StaleBvh when either is a stale Manual
mesh (the lower id first).
Sourcepub fn mesh_distance(
&mut self,
a: MeshId,
b: MeshId,
max_distance: f64,
) -> Result<Option<SceneMeshDistance>>
pub fn mesh_distance( &mut self, a: MeshId, b: MeshId, max_distance: f64, ) -> Result<Option<SceneMeshDistance>>
The distance between the surfaces of meshes a and b as placed in
the world, with a closest pair of points in the world, or None when
it is greater than max_distance (inclusive, may be infinite) or a
mesh has no triangle.
Phase 3’s fast_mesh_query::mesh_distance runs in A’s space with
max_distance rounded up to f32; the result is kept only when its
distance is within the exact bound. Distances carry over unchanged
with rigid placements, times A’s uniform scale otherwise; with a
non-uniformly scaled A the query runs on copies baked into the world
(see Scene::bake_pair_inner). Only these two BVHs are brought up
to date.
§Errors
SceneError::UnknownMesh; SceneError::InvalidInput for a
negative or NaN max_distance; then as for Scene::intersects.
Sourcepub fn triangles_near(
&mut self,
a: MeshId,
b: MeshId,
margin: f64,
out_a: &mut Vec<TriangleId>,
out_b: &mut Vec<TriangleId>,
) -> Result<()>
pub fn triangles_near( &mut self, a: MeshId, b: MeshId, margin: f64, out_a: &mut Vec<TriangleId>, out_b: &mut Vec<TriangleId>, ) -> Result<()>
Appends to out_a the triangles of mesh a within margin of mesh
b, and to out_b those of b within margin of a, as placed in
the world: Phase 3’s fast_mesh_query::triangles_near in A’s space.
Elements already in the vectors stay in front; each appended part is
ascending without duplicates. Only these two BVHs are brought up to
date. With a scaled placement on either side the query runs on a copy
baked into A’s local space (or into the world when A is
non-uniformly scaled); passing the same id twice lists every alive
triangle of the mesh in both vectors.
margin is rounded up to f32. The lists cannot be filtered again
per triangle, so when margin is not an f32 value they may hold
triangles up to one f32 step (relative 6e-8) beyond it.
§Errors
SceneError::UnknownMesh; SceneError::InvalidInput for a
negative or NaN margin; then as for Scene::intersects, or
SceneError::Query with OutOfMemory when a vector cannot grow. On
any error both vectors keep their lengths.
Source§impl Scene
impl Scene
Sourcepub fn register(
&mut self,
moving: MeshId,
fixed: MeshId,
options: &RegisterOptions,
) -> Result<RegisterReport>
pub fn register( &mut self, moving: MeshId, fixed: MeshId, options: &RegisterOptions, ) -> Result<RegisterReport>
Rigidly aligns the mesh moving to the mesh fixed by point-to-plane
ICP (fast_mesh_ops::icp()), using points on moving’s surface and
fixed’s BVH.
The initial guess is the current placements. ICP is local, so put
the meshes roughly in place first, with Scene::set_placement; a
good guess is off by a small part of the shape’s features.
Applying. With RegisterOptions::apply (the default) a good result
becomes moving’s placement as one undo step, or as part of the open
step. Good means converged, with rmse within
RegisterOptions::max_rmse and enough points in range (NotApplied
says which failed). Anything else changes nothing, whatever the option,
but its estimate is returned; set it with Scene::set_placement if it
will do.
Undetermined poses. A sphere’s spin, a cylinder’s spin and a plane’s
slide are not fixed by the data, though facets or noise can make the
iteration settle on some value with a tiny rmse. Those report
IcpStatus::Underconstrained, not converged, and list the motions in
undetermined. Coarse regular meshes count too: a 16-sided sphere has
exact fits 22.5 degrees apart.
Scales. Only rotation and translation are solved. moving’s scale
is applied to its points and kept as it is. fixed’s scale, uniform
or not, is followed exactly, on a copy of fixed baked through it with
its own BVH, so each such call costs a BVH build. Distances and options
are in world units either way.
Partial overlap. Set IcpOptions::overlap a little below the
fraction of moving that lies over fixed, or nothing is rejected.
Only fixed’s BVH is used, and only it is brought up to date.
§Errors
SceneError::UnknownMesh for a stale id;
SceneError::InvalidInput when the ids are one mesh, max_samples is
zero or max_rmse is negative or NaN; SceneError::StaleBvh for a stale Manual fixed;
SceneError::Ops when a mesh has no triangles, an option is invalid,
or a placement takes the points out of f32 range in fixed’s
frame. On error the scene is unchanged.
Source§impl Scene
impl Scene
Sourcepub fn new(options: SceneOptions) -> Scene
pub fn new(options: SceneOptions) -> Scene
An empty scene.
Sourcepub fn add_mesh(&mut self, mesh: Mesh, options: MeshOptions) -> Result<MeshId>
pub fn add_mesh(&mut self, mesh: Mesh, options: MeshOptions) -> Result<MeshId>
Adds a mesh, building its BVH, and returns its id. With
MeshOptions::defer_bvh a Lazy or Manual mesh builds its BVH on
first use instead (its first update, query or flush), since nothing
needs it before then.
§Errors
SceneError::InvalidInput for an invalid placement, or a BVH or
memory error from the build. An invalid policy is refused before
anything is built. The scene is unchanged on error.
Sourcepub fn add_mesh_built(&mut self, build: MeshBuild) -> Result<MeshId>
pub fn add_mesh_built(&mut self, build: MeshBuild) -> Result<MeshId>
Adds a mesh built in steps by build (see MeshBuild), first
finishing what is left of its BVH and normals, and returns its id.
The mesh, its BVH, its normals and everything reported are the same
as from Scene::add_mesh with the same mesh and options, followed
by Scene::set_normals when the build has normals on.
§Errors
As for Scene::add_mesh. The scene is unchanged on error.
Sourcepub fn remove_mesh(&mut self, id: MeshId) -> Result<Mesh>
pub fn remove_mesh(&mut self, id: MeshId) -> Result<Mesh>
Removes a mesh and returns it. The id never matches again. Its
history entries (undo, redo and in an open step) are dropped, steps
left empty with them, and its patches release the slots they reserve.
The removal shows up in every subscriber’s next
Scene::take_changes_for, unless the mesh was added since that
subscriber’s last call.
The fields on the mesh and those measured to it alone are removed
with it (see Scene::remove_field), and so are colourings by them.
A field measured to it and to other meshes keeps the others: it is
recomputed in full, at once when it is Eager. The
mesh leaves every section selecting it, which is reported in its
final MeshChanges::sections_changed.
§Errors
SceneError::UnknownMesh for a stale id.
Sourcepub fn edit<R, E: Into<SceneError>>(
&mut self,
id: MeshId,
f: impl FnOnce(&mut Transaction<'_>) -> Result<R, E>,
) -> Result<R>
pub fn edit<R, E: Into<SceneError>>( &mut self, id: MeshId, f: impl FnOnce(&mut Transaction<'_>) -> Result<R, E>, ) -> Result<R>
Runs f in a transaction on mesh id, commits it, and records the
patch in the history: in the open step, or as a step of its own when
none is open. Recording drops the redo stack. The changes are added to
the mesh’s report and to its BVH’s pending changes; an Eager BVH is
then brought up to date, and so are the Eager fields and section
entries involving the mesh (a failed update leaves them stale and
never fails the edit).
An empty transaction records and reports nothing.
If the Eager BVH update fails (for example out of memory), the edit
still succeeds: the BVH keeps its pending changes and is treated like
Lazy until Scene::update, Scene::flush or a query updates it.
f may fail with any error that converts into SceneError: a
store error, or an OpsError from a repair
operation, which becomes SceneError::Ops (out-of-memory becomes
SceneError::Store, however it was raised). A closure whose body
never fails cannot infer its error type (E0283) and must name it, for
example scene.edit(id, |_| Ok::<(), StoreError>(())).
§Errors
SceneError::UnknownMesh for a stale id; f’s error, converted
(for example SceneError::Store or SceneError::Ops), when it
fails; or SceneError::Store when the commit fails or there is no
memory to record the patch. The transaction is then rolled back and
the scene (including an open step) is unchanged.
Sourcepub fn begin_step(&mut self)
pub fn begin_step(&mut self)
Opens a history step, or one more nesting level of the open step.
Edits and placement changes until the matching Scene::end_step
are undone and redone together, across meshes.
Sourcepub fn end_step(&mut self) -> Result<()>
pub fn end_step(&mut self) -> Result<()>
Ends one nesting level of the open step; the outermost call closes it. A step with no entries is not recorded. Closing may evict the oldest steps to meet the history budget.
§Errors
SceneError::StepNotOpen when no step is open.
Sourcepub fn cancel_step(&mut self) -> Result<()>
pub fn cancel_step(&mut self) -> Result<()>
Reverts the open step’s entries, in reverse order, and discards the step, however deeply nested (for example on Esc mid-drag). The reverts are reported and update BVHs like an undo.
§Errors
SceneError::StepNotOpen when no step is open. A store error (for
example out of memory) leaves the meshes and the open step unchanged;
SceneError::Corrupted means that even restoring them failed, with
the consequences described for Scene::undo.
Sourcepub fn undo(&mut self) -> Result<bool>
pub fn undo(&mut self) -> Result<bool>
Closes an open step, then undoes the latest step: its entries are
reverted in reverse order, all or nothing. Returns false when there
is nothing to undo. The changes are reported and reach the BVHs as
for Scene::edit; a placement entry gets its old value back and is
reported as placement_changed.
A non-empty open step is the latest step, and it is undone even when it is larger than the whole history budget (Ctrl+Z mid-drag undoes the drag). The budget is applied afterwards, which may evict the oldest undo steps and, for a step larger than the budget, drop it from the redo stack again.
§Errors
A store error (for example out of memory): the meshes, both stacks
and an open step are then unchanged (the step stays open).
SceneError::Corrupted if restoring them after such an error
failed too: the failed step is dropped from its stack (an open step
is discarded), the meshes it edits may be partly changed, each of
them is reported as fully changed (changes: None) and its BVH is
rebuilt from scratch on its next update (right away for Eager), and
each mesh with a placement entry in it is reported as
placement_changed. The history may no longer match the meshes, so
the caller should consider Scene::clear_history.
Sourcepub fn redo(&mut self) -> Result<bool>
pub fn redo(&mut self) -> Result<bool>
Closes an open step, then redoes the latest undone step: its entries
are re-applied in order, all or nothing. Returns false when there is
nothing to redo. Reporting and errors as for Scene::undo.
§Errors
As for Scene::undo.
Sourcepub fn can_undo(&self) -> bool
pub fn can_undo(&self) -> bool
True if Scene::undo would undo something, counting a non-empty
open step.
Sourcepub fn can_redo(&self) -> bool
pub fn can_redo(&self) -> bool
True if Scene::redo would redo something.
Sourcepub fn clear_history(&mut self) -> Result<()>
pub fn clear_history(&mut self) -> Result<()>
Closes an open step, then drops every undo and redo step, releasing the slots their patches reserve. The meshes are not changed.
§Errors
None at present; the Result leaves room for future checks.
Sourcepub fn set_mode(&mut self, id: MeshId, mode: UpdateMode) -> Result<()>
pub fn set_mode(&mut self, id: MeshId, mode: UpdateMode) -> Result<()>
Sets when the mesh’s BVH is brought up to date. Switching to
UpdateMode::Eager updates a stale BVH right away; if that update
fails, the mode is still set and the BVH stays pending, as after a
failed Eager update in Scene::edit.
§Errors
SceneError::UnknownMesh for a stale id.
Sourcepub fn mode(&self, id: MeshId) -> Result<UpdateMode>
pub fn mode(&self, id: MeshId) -> Result<UpdateMode>
When the mesh’s BVH is brought up to date (see Scene::set_mode).
§Errors
SceneError::UnknownMesh for a stale id.
Sourcepub fn update(&mut self, id: MeshId) -> Result<()>
pub fn update(&mut self, id: MeshId) -> Result<()>
Brings the mesh’s BVH, and its normals if they are on, up to date
now, whatever its mode. Eager fields involving the mesh that were
left stale (for example by this BVH being a stale Manual one) then
catch up, unless Eager field updates are deferred (see
Scene::set_defer_fields): they then stay due. Every stale section
entry of the mesh catches up too, whatever its mode.
§Errors
SceneError::UnknownMesh, or a BVH or memory error from the update
of the BVH or the normals (both are attempted). On error they keep
their pending changes. Then the first section error (for example out
of memory); such entries stay stale.
Sourcepub fn flush(&mut self) -> Result<()>
pub fn flush(&mut self) -> Result<()>
Brings every Lazy BVH up to date, and every Eager one left stale by a
failed update, and the same for the normals (see
Scene::set_normals); then does the same for the fields, which
follow the mode of the mesh they are on (see
Scene::update_fields), and for the section entries, which follow
the mode of their mesh (see Scene::update_sections). Manual BVHs,
and fields and section entries on Manual meshes, are left alone.
§Errors
The first BVH, memory or field error, for example
SceneError::StaleBvh for a field measured to a stale Manual mesh:
such a field makes every flush return StaleBvh until that BVH is
brought up to date with Scene::update. Every mesh and field is
still attempted; those that failed keep their pending changes.
Sourcepub fn take_changes(&mut self) -> Vec<MeshChanges>
pub fn take_changes(&mut self) -> Vec<MeshChanges>
Everything that happened to the meshes since the last call, one entry
per affected mesh in id order, then resets every report of the
default subscriber. Other subscribers keep theirs (see
Scene::subscribe).
A mesh added and removed between two calls is not reported, and neither is a mesh whose changes cancel out (for example vertices added and removed again).
Sourcepub fn subscribe(&mut self) -> SubscriberId
pub fn subscribe(&mut self) -> SubscriberId
Adds a consumer of change reports and returns its id. It starts with
a clean report for every mesh, so it sees only what happens from now
on, except for colours: a mesh that already has a colouring starts
with colors_dirty: None, so the subscriber reads every colour once.
It drains its reports with Scene::take_changes_for. Every
subscriber is told about the same changes, merged the same way.
A subscriber that never drains keeps accumulating reports (merged
change sets and removals) until it is drained or unsubscribed.
Sourcepub fn unsubscribe(&mut self, id: SubscriberId) -> Result<()>
pub fn unsubscribe(&mut self, id: SubscriberId) -> Result<()>
Removes a subscriber and drops its pending reports. Its id is rejected from then on.
§Errors
SceneError::InvalidInput for an unknown or already removed id, or
for the default subscriber (which backs Scene::take_changes).
Sourcepub fn take_changes_for(&mut self, id: SubscriberId) -> Result<Vec<MeshChanges>>
pub fn take_changes_for(&mut self, id: SubscriberId) -> Result<Vec<MeshChanges>>
Scene::take_changes for subscriber id: everything that happened
to the meshes since its last call (or since it subscribed), one entry
per affected mesh in id order, then resets its reports.
§Errors
SceneError::InvalidInput for an unknown or removed subscriber.
Sourcepub fn add_channel(&mut self, id: MeshId, desc: ChannelDesc) -> Result<()>
pub fn add_channel(&mut self, id: MeshId, desc: ChannelDesc) -> Result<()>
Adds a channel to the mesh, filled with its default value. Not
undoable, as in the store; reported in
MeshChanges::channels_written. Names starting with field: are
reserved for the scene’s fields.
§Errors
SceneError::InvalidInput for a reserved name,
SceneError::UnknownMesh, or the store’s error (for example a
duplicate name). The scene is unchanged on error.
Sourcepub fn capture_rest_sizes(
&mut self,
id: MeshId,
only_if_missing: bool,
) -> Result<()>
pub fn capture_rest_sizes( &mut self, id: MeshId, only_if_missing: bool, ) -> Result<()>
Records the mesh’s rest sizes for
split_stretched; see
capture_rest_sizes. Not
an edit: no undo step and no change report, since no geometry changed
and nothing draws this channel. With only_if_missing, valid rest sizes
stay as they are (ensure_rest_sizes).
§Errors
SceneError::UnknownMesh, or SceneError::Ops when memory runs out.
Sourcepub fn ensure_incidence(&mut self, id: MeshId) -> Result<()>
pub fn ensure_incidence(&mut self, id: MeshId) -> Result<()>
Builds the mesh’s vertex index if it is not cached, so that an operation run next can follow it instead of scanning every triangle.
§Errors
SceneError::UnknownMesh, or the store’s error when memory runs out.
Sourcepub fn remove_channel(&mut self, id: MeshId, name: &str) -> Result<ChannelDesc>
pub fn remove_channel(&mut self, id: MeshId, name: &str) -> Result<ChannelDesc>
Removes a channel from the mesh and returns its description. Not
undoable, as in the store; reported in
MeshChanges::channels_written. Recorded patches skip the removed
channel from then on, so undo and redo will not restore the values of
a removed source channel.
§Errors
SceneError::InvalidInput for a reserved name (starting with
field:), SceneError::UnknownMesh, or the store’s error for an
unknown name.
Sourcepub fn derived_channel_mut(
&mut self,
id: MeshId,
name: &str,
) -> Result<&mut [f32]>
pub fn derived_channel_mut( &mut self, id: MeshId, name: &str, ) -> Result<&mut [f32]>
Writable values of a derived channel. Writes are not undoable, as in
the store. The call itself is reported in
MeshChanges::channels_written, since the slice may be written
after it returns.
§Errors
SceneError::InvalidInput for a reserved name (starting with
field:), SceneError::UnknownMesh, or the store’s error for an
unknown or non-derived channel.
Sourcepub fn compact(&mut self, id: MeshId) -> Result<Remap>
pub fn compact(&mut self, id: MeshId) -> Result<Remap>
Removes the mesh’s dead slots and renumbers the rest (see
Mesh::compact). The mesh’s recorded patches no longer apply, so
its edit entries leave the undo and redo stacks and an open step;
steps left empty are dropped. Its placement entries stay valid and
are kept. Nothing is released: the reserved slots no longer exist.
Its BVH is rebuilt whatever its mode, and the next
Scene::take_changes reports it as fully changed (changes: None,
colors_dirty: None, normals_dirty: None). Its field channels and
colours are remapped with it, and its normals recomputed in full,
whatever its mode; the fields involving it are recomputed in full on
their next update, and so are its section entries.
If the rebuild (or the normals) fails, compaction still succeeds and
the BVH (or the normals) stays pending, as after a failed Eager
update in Scene::edit.
§Errors
SceneError::UnknownMesh, or a store error from the compaction; the
scene is then unchanged.
Sourcepub fn mesh_id(&self, index: u32, generation: u32) -> Option<MeshId>
pub fn mesh_id(&self, index: u32, generation: u32) -> Option<MeshId>
The id of the live mesh with this MeshId::index and
MeshId::generation, or None when there is none (never added,
or removed). For ids passed back across an FFI boundary: a stale or
made-up pair cannot become a live id.
Sourcepub fn set_placement(&mut self, id: MeshId, placement: Placement) -> Result<()>
pub fn set_placement(&mut self, id: MeshId, placement: Placement) -> Result<()>
Moves the mesh. Stores the placement, reports it as
placement_changed and records the old and new value in the history
(in the open step, or as a step of its own), which drops the redo
stack. Setting the current placement again records and reports
nothing. No BVH is touched; Eager fields and section entries
involving the mesh are updated (a failure leaves them stale).
Within an open step, consecutive placement changes of the same mesh merge into one entry that keeps the first old value and the last new one, so a drag of any length records one entry and undo still restores the placement from before the drag. Any other entry in between (an edit, or another mesh’s placement) starts a new entry.
§Errors
SceneError::UnknownMesh, SceneError::InvalidInput when the
rotation is not a proper rotation or the scale is not finite and
positive, or SceneError::Store when there is no memory to record
it. The scene is unchanged on error.
Sourcepub fn is_current(&self, id: MeshId) -> Result<bool>
pub fn is_current(&self, id: MeshId) -> Result<bool>
Sourcepub fn bounds(&self, id: MeshId) -> Result<Option<Aabb>>
pub fn bounds(&self, id: MeshId) -> Result<Option<Aabb>>
The box around the vertices the live triangles use, in the mesh’s
stored local coordinates, or None without live triangles. Dead
slots keep stale positions, and a live vertex no live triangle uses
is not drawn either, so neither widens it.
§Errors
SceneError::UnknownMesh for a stale id.
Source§impl Scene
impl Scene
Sourcepub fn dab(&mut self, id: MeshId, dab: &Dab) -> Result<DabReport>
pub fn dab(&mut self, id: MeshId, dab: &Dab) -> Result<DabReport>
Applies one brush dab as one edit: the same history, reports and
failure behaviour as Scene::edit with the matching
deform function, and the same result, bit
for bit, except that a vertex no triangle uses is out of the brush’s
reach. The cost follows the vertices under the brush, plus a walk down
the BVH, however large the mesh is; where the BVH cannot serve (stale
under UpdateMode::Manual) it scans the mesh instead.
The first dab on a mesh builds its vertex-to-triangles index, once.
§Errors
As for Scene::edit with the deform function:
SceneError::UnknownMesh for a stale id, SceneError::Ops for an
invalid brush, SceneError::Store when memory runs out. Nothing
changes in any of these cases.
Sourcepub fn dab_protected(
&mut self,
id: MeshId,
dab: &Dab,
vertices: &[VertexId],
weights: &[f32],
) -> Result<DabReport>
pub fn dab_protected( &mut self, id: MeshId, dab: &Dab, vertices: &[VertexId], weights: &[f32], ) -> Result<DabReport>
Scene::dab under with_protection: each listed vertex’s move is
scaled by its weight, at a cost that follows the brush region plus the
list. List only what the brush can reach.
A dab with every vertex under its brush held fully (weight 0) moves nothing, so it edits nothing either: it reports 0 and leaves no undo step.
§Errors
As for Scene::dab, and as check_protection for the list.
Nothing changes in any of these cases.
Source§impl Scene
impl Scene
Sourcepub fn add_section(&mut self, desc: SectionDesc) -> Result<SectionId>
pub fn add_section(&mut self, desc: SectionDesc) -> Result<SectionId>
Registers a plane section of the meshes desc.meshes and returns its
id. Sections are not in the history: undo does not move planes.
Each selected mesh gets its own SectionResult, which follows the
UpdateMode of that mesh: an Eager mesh’s is computed right away
and after every edit, placement change, undo, redo or cancel of the
mesh, and after every plane or fill change; a Lazy one’s by
Scene::flush, Scene::update or Scene::update_sections; a
Manual one’s by Scene::update or Scene::update_sections. A
failed Eager computation is swallowed and leaves the entry stale.
Until its first computation an entry reads as an empty result with
status SectionStatus::Stale.
Results that change are reported in the mesh’s
MeshChanges::sections_changed.
§Errors
SceneError::UnknownMesh for a stale mesh id;
SceneError::InvalidInput for a mesh listed twice; a memory error.
Never SceneError::StaleBvh. The scene is unchanged on error.
Sourcepub fn remove_section(&mut self, id: SectionId) -> Result<()>
pub fn remove_section(&mut self, id: SectionId) -> Result<()>
Removes a section. The removal is reported in the
MeshChanges::sections_changed
of every mesh it selected, and the id is rejected from then on.
§Errors
SceneError::UnknownSection for an unknown or removed section.
Sourcepub fn set_section_plane(&mut self, id: SectionId, plane: Plane) -> Result<()>
pub fn set_section_plane(&mut self, id: SectionId, plane: Plane) -> Result<()>
Moves a section’s plane. Every entry of the section becomes stale (Eager ones are recomputed right away); nothing else is touched. Computing an Eager entry needs a current BVH, so an Eager mesh whose earlier BVH update failed has that update retried here.
§Errors
SceneError::UnknownSection for an unknown or removed section.
Sourcepub fn set_section_meshes(
&mut self,
id: SectionId,
meshes: Vec<MeshId>,
) -> Result<()>
pub fn set_section_meshes( &mut self, id: SectionId, meshes: Vec<MeshId>, ) -> Result<()>
Changes the meshes a section cuts. Meshes it keeps keep their entries;
added meshes start stale (Eager ones are computed right away); removed
meshes drop their entries, which is reported in their
MeshChanges::sections_changed.
§Errors
SceneError::UnknownSection; SceneError::UnknownMesh for a
stale mesh id; SceneError::InvalidInput for a mesh listed twice; a
memory error. Never SceneError::StaleBvh. The scene is unchanged
on error.
Sourcepub fn set_section_fill(&mut self, id: SectionId, fill: bool) -> Result<()>
pub fn set_section_fill(&mut self, id: SectionId, fill: bool) -> Result<()>
Turns a section’s fill on or off. Every entry of the section becomes
stale (Eager ones are recomputed right away); nothing else is touched.
As with Scene::set_section_plane, an Eager mesh whose earlier BVH
update failed has that update retried.
§Errors
SceneError::UnknownSection for an unknown or removed section.
Sourcepub fn update_sections(&mut self) -> Result<()>
pub fn update_sections(&mut self) -> Result<()>
Computes every stale section entry, whatever the mode of its mesh,
bringing the BVHs it needs up to date under the query rules (Lazy
ones are updated). Renderers call this (or Scene::flush), then
read any number of results.
§Errors
The first error, for example SceneError::StaleBvh for an entry
whose mesh has a stale Manual BVH: such an entry stays stale, and
makes every call return StaleBvh until that BVH is brought up to
date with Scene::update. Every entry is still attempted.
Sourcepub fn section(&self, id: SectionId, mesh: MeshId) -> Result<&SectionResult>
pub fn section(&self, id: SectionId, mesh: MeshId) -> Result<&SectionResult>
The section’s result for mesh as of its last computation (see
Scene::section_status); empty before the first one. Never
updates.
§Errors
SceneError::UnknownSection; SceneError::UnknownMesh for a
stale mesh id; SceneError::InvalidInput for a live mesh the
section does not select.
Sourcepub fn section_desc(&self, id: SectionId) -> Result<&SectionDesc>
pub fn section_desc(&self, id: SectionId) -> Result<&SectionDesc>
The section’s description as last set: its plane (the one
Scene::set_section_plane gave, which results not yet recomputed
may lag behind; see Scene::section_plane), meshes and fill.
§Errors
SceneError::UnknownSection for an unknown or removed section.
Sourcepub fn section_status(
&self,
id: SectionId,
mesh: MeshId,
) -> Result<SectionStatus>
pub fn section_status( &self, id: SectionId, mesh: MeshId, ) -> Result<SectionStatus>
Sourcepub fn section_plane(
&self,
id: SectionId,
mesh: MeshId,
) -> Result<Option<Plane>>
pub fn section_plane( &self, id: SectionId, mesh: MeshId, ) -> Result<Option<Plane>>
The world plane the section’s result for mesh was computed with,
whose (u, v) frame its 2D points and fill are in; None before the
first computation. It differs from the section’s plane while a plane
move is not yet computed. Never updates.
§Errors
As for Scene::section.
Sourcepub fn section_revision(&self, id: SectionId, mesh: MeshId) -> Result<u64>
pub fn section_revision(&self, id: SectionId, mesh: MeshId) -> Result<u64>
How many times the section’s result for mesh has changed: 0 before
its first computation, then up by one per computation whose result
differs (a recompute with an identical result leaves it alone).
Bindings cache per-result data (like GPU buffers) against it instead
of draining a subscriber. Never updates.
§Errors
As for Scene::section.
Sourcepub fn section_gap(
&self,
id: SectionId,
a: MeshId,
b: MeshId,
) -> Result<Option<Gap>>
pub fn section_gap( &self, id: SectionId, a: MeshId, b: MeshId, ) -> Result<Option<Gap>>
The closest pair between the contours of meshes a and b in the
section, measured in the plane, with its points in the world; None
when either has no contour segments. Never updates: it reads the last
computed results, so for a stale entry (see Scene::section_status)
it describes the scene as of that computation. A gap is only defined
within one plane: when the two results were computed with different
planes (one was updated after a plane move, the other not yet), it is
None; call Scene::update_sections first.
§Errors
As for Scene::section, for either mesh;
SceneError::InvalidInput when a and b are the same mesh; a
memory error.
Sourcepub fn section_id(&self, raw: u32) -> Option<SectionId>
pub fn section_id(&self, raw: u32) -> Option<SectionId>
The id of the section with this SectionId::raw value, or None
when there is none (never added, or removed).