Desktop 3D¤
An interactive desktop 3D viewer built on compas_viewer with a scene tree, element selection, and animation support.
Note
This viewer needs optional dependencies included in the viz
extra. Without them, the viewer degrades to a null object that warns on use.
Viewer
¤
Viewer(width: int | None = None, height: int | None = None, show_grid: bool | None = None, config: Config | None = None, **kwargs: Any)
A thin wrapper on compas_viewer.Viewer.
It subclasses the COMPAS viewer so that camera control, the on frame
loop, show and recording all work natively. The force density
datastructures render through their registered scene objects, so add
only provides the terser viewer.add(obj) interface and a couple of
kwarg conveniences.
For convenience it also accepts the width, height and show_grid
keyword arguments directly and folds them into a
compas_viewer.config.Config,
so the common window setup does not require building a config by hand.
The defaults (1200x800, no grid) fit a typical laptop screen and keep the
grid from cutting through structures that hang below z=0.
The viewer is a process-wide singleton (a compas_viewer constraint):
a second Viewer() call returns the same instance with its constructor
arguments ignored. To visualize several results in one process — e.g. one
per step of a sequential optimization — reuse the instance::
viewer = Viewer()
for step in steps:
viewer.clear()
viewer.add(...)
viewer.show()
The window closes between shows while the camera carries over.
clear
¤
clear() -> None
Empty the scene for the next round of adds.
Call between sequential shows, while the window is closed. Besides the scene objects this also drops the picking-color registrations, which the parent scene never prunes.
update
¤
update() -> None
Repaint the viewer window immediately.
Schedules a repaint and drains the event queue so it happens now,
painting whatever the scene objects currently hold. This acts at the
window layer: it does not touch scene data, so refresh the buffers of
any mutated object first (e.g. scene_object.update()).
Notes
The intended use is animating a blocking computation that runs on the GUI thread. Because the computation blocks Qt's event loop, a normally scheduled repaint would not be serviced until it returns and every frame would collapse into one. Calling this per step forces each frame to paint while the computation is still running. A computation on a worker thread does not need it: the viewer repaints on its own timer.
show
¤
show() -> None
Show the viewer window and block until it is closed.
The window can be shown again after closing: a re-show rebuilds the GL
render buffers for the current scene, and running is reset on
return so that between-show add calls stay lightweight (no per-add
buffer and sidebar rebuild).
on
¤
on(interval: int, frames: int | None = None) -> Callable[[Callable[..., None]], Callable[..., None]]
Decorate a frame callback for the animation loop.
Warns once when per-element scene objects are in the scene: their
buffers update one by one with a full-buffer index lookup each, per
frame, so animation slows quadratically with element count. Re-add
the datastructure with fuse=True to animate on batched soups.
add
¤
add(data: Geometry | Datastructure, **kwargs: Any) -> SceneObject
Add a data object to the viewer.
This is a convenience shortcut for viewer.scene.add with a couple
of kwarg conveniences for plain COMPAS objects. The force density
datastructures dispatch through the scene registry to their scene
objects (FDNetworkObject, FDMeshObject).
Dispatch is purely by type. To draw a force-density datastructure as plain
geometry instead (a bare wireframe or shaded surface), convert it to its
COMPAS base first and add that, e.g. viewer.add(mesh.copy(cls=Mesh))
or viewer.add(network.copy(cls=Network)).
Parameters:
-
data(Geometry | Datastructure) –The geometry or datastructure to visualize.
-
kwargs(Any, default:{}) –Additional visualization options passed to the scene object.
Returns:
-
scene_object(SceneObject) –The created scene object.