Creating a Mesh
SCADview's primary use it to help you iteratively create a mesh.
When you load/reload a Python script into SCADview as you work on it,
it executes the create_mesh function,
and shows the returned mesh.
create_mesh Signature
The function create_mesh must:
- Take no parameters, or all parameters must have default values.
- Return a
Trimesh,Manifoldorlist[Trimesh | Manifold]or... see below.
That is, the function should look like this with type hints (but type hints are not required):
from manifold3d import Manifold
from trimesh import Trimesh
def create_mesh() -> Trimesh | Manifold | list[Trimesh | Manifold]:
...
Interactive Parameters
Defaulted bool, int, float, and str parameters appear in the
Parameters section after the script loads. Their values are passed to
create_mesh by keyword when the mesh is rebuilt:
from trimesh.creation import box
def create_mesh(width: float = 2.5, include_lid: bool = True):
mesh = box([width, width, 1])
return mesh if include_lid else box([width, width, 0.5])
Only ordinary named and keyword-only parameters with one of those exact built-in
default types are controllable. Positional-only and variadic parameters,
required parameters, and defaults such as None, paths, containers, enums,
NumPy scalars, and custom subclasses do not get controls. Required parameters
still cause the normal load error when create_mesh is invoked.
The stack_of_balls.py example demonstrates
all five supported control types in a deterministic model.
Trimesh vs Manifold
You can choose to return either Trimesh or Manifold types,
or a list containing items of either type.
The list does not need to have just one type.
Trimesh is simpler to use than
manifold3d,
which creates Manifold objects.
But manifold3d is highly optimized for geometric boolean operations,
and can be much faster than Trimesh.
So if you are combining 100s of meshes, consider trying out manifold3d.
Toggleable Features
SCADview can expose optional geometry as UI-togglable features.
Use feature on a mesh-returning function
or method:
from trimesh.creation import box, cylinder
from scadview import feature
@feature
def guide():
return box([20, 10, 8])
@feature("cutout")
def cutout():
return cylinder(radius=3, height=20)
You can also wrap a mesh directly with feature("name", mesh):
from trimesh.creation import box
from scadview import feature
def create_mesh():
base = box([40, 20, 10])
guide = feature("guide", box([20, 10, 8]))
return base.union(guide)
Feature-decorated functions and methods must return a Trimesh or Manifold.
Decorating classes is not supported.
Disabled features behave like identity operands for supported boolean operations:
Trimesh:union(...),difference(...),intersection(...)Manifold:+,-,^
That lets you write expressions such as:
def create_mesh():
base = box([40, 20, 10])
return base.union(guide()).difference(cutout())
When the script is loaded, each discovered feature appears in the UI and can be toggled on or off without editing the script.
Features are enabled by default. Use
feature_default to make a named
feature start disabled when no UI override exists:
from trimesh.creation import box
from scadview import feature, feature_default
feature_default("supports", enabled=False)
def create_mesh():
base = box([40, 20, 10])
support_a = feature("supports", box([4, 4, 20]))
support_b = feature("supports", box([4, 4, 20]))
return base.union(support_a).union(support_b)
Defaults apply by feature name, so every mesh registered as "supports" uses the
same default. If the UI has already toggled a feature, that UI state takes
precedence over the script default. Repeating the same default is allowed, but
declaring conflicting defaults for the same feature name raises ValueError.
Debug Features
The Features section also has a Debug features toggle. It is off by default and remains selected for the current application session. When selected, SCADview shows each enabled feature's registered source geometry as translucent debug output instead of the final mesh. This is useful for inspecting subtractive tool volumes, which may not contribute triangles to the final model.
Debug features does not change whether a feature is enabled. Clearing a feature
checkbox omits that feature from the debug output; selecting Debug features again
does not re-enable it. Because this is diagnostic output, Export is unavailable
while it is displayed. Debug features shows only source meshes registered with
feature(...); meshes not marked as features are omitted from this visualization.
Debug Mode: Return a list
Returning a list of objects results in SCADview
displaying each object in the list.
It is intended to be used for debugging purposes.
Sometimes, if you are getting unexpected results,
returning the objects in the list
rather than as a single mesh before you've combined them,
you can see what went wrong.
Note when returning a list,
the "Export" feature is not available.
Using Color and Transparency
set_mesh_color may be applied to a Trimesh,
which affects its color and transparency.
This allows you to see different meshes in the list in different colors,
and make them transparent so you can see other meshes hidden inside.
set_mesh_color only works for Trimesh objects,
and colors do not survive boolean operations.
set_mesh_color can also be useful when returning a single Trimesh,
for example if you are removing hidded voids.
Output and Logging
Console output goes to the terminal where you launched scadview.
You can use print(...) or Python's logging module inside your script. If you
need more detail, you can set the logging level in your script.
Incremental Builds
Displaying intermediate builds of your mesh as you build it can be useful to see problems before a long build completes. It also give you a sense of how long the build might take.
SCADview supports incremental builds. To do this,
create_mesh can be defined as a Generator,
with the signature:
def create_mesh() -> Generator[[Trimesh | Manifold | list[Trimesh | Manifold]]:
yield ...
def create_mesh():
..create mesh1
yield mesh1
...create mesh2
yield mesh2
As this adds additional renders, building incrementatlly is generally slower than a single build. If you yield very quickly (many times per second), some renders may be skipped to keep the speed up.
As with create_mesh as a "regular" function,
you can yield a singular mesh or a list of them.
As above, yielding a list also puts SCADview into debug mode.
Animation
By pausing between each yield, you can animate at a consistent frame rate.
For example:
from time import sleep
from trimesh.creation import box
def create_mesh():
b = box([10, 10, 20])
for _ in range(100):
yield b
sleep(0.1)
b.apply_translation([0.2, 0, 0])