Skip to content

Commit 447c282

Browse files
committed
docs(vtk): add modern remote/local rendering switch
1 parent d083103 commit 447c282

1 file changed

Lines changed: 131 additions & 0 deletions

File tree

  • examples/06_vtk/05_remote_local
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
#!/usr/bin/env -S uv run --script
2+
#
3+
# /// script
4+
# requires-python = ">=3.12"
5+
# dependencies = [
6+
# "trame>=3.12",
7+
# "trame-vtklocal",
8+
# "trame-rca",
9+
# "trame-vuetify",
10+
# "vtk>=9.6",
11+
# ]
12+
#
13+
# [tool.uv]
14+
# prerelease = "allow"
15+
#
16+
# [[tool.uv.index]]
17+
# url = "https://wheels.vtk.org"
18+
# ///
19+
import vtk
20+
21+
from trame.app import TrameApp
22+
from trame.decorators import change
23+
from trame.ui.vuetify3 import VAppLayout
24+
from trame.ui.html import DivLayout
25+
from trame.widgets import rca, vtklocal, client
26+
from trame.widgets import vuetify3 as v3
27+
28+
OVERLAY = "position:absolute;top:1rem;left:1rem;z-index:10;"
29+
30+
31+
class ClientRemoteRendering(TrameApp):
32+
def __init__(self, server=None):
33+
super().__init__(server)
34+
self._setup_vtk()
35+
self._build_ui()
36+
37+
def _setup_vtk(self):
38+
renderer = vtk.vtkRenderer()
39+
render_window = vtk.vtkRenderWindow()
40+
render_window.AddRenderer(renderer)
41+
render_window.OffScreenRenderingOn()
42+
43+
render_window_interactor = vtk.vtkRenderWindowInteractor()
44+
render_window_interactor.SetRenderWindow(render_window)
45+
render_window_interactor.GetInteractorStyle().SetCurrentStyleToTrackballCamera()
46+
47+
cone_source = vtk.vtkConeSource()
48+
mapper = vtk.vtkPolyDataMapper()
49+
actor = vtk.vtkActor()
50+
mapper.SetInputConnection(cone_source.GetOutputPort())
51+
actor.SetMapper(mapper)
52+
renderer.AddActor(actor)
53+
renderer.ResetCamera()
54+
render_window.Render()
55+
56+
self.render_window = render_window
57+
self.cone = cone_source
58+
59+
def _build_ui(self):
60+
# WASM Rendering
61+
self.state.setdefault("local_camera", {})
62+
with DivLayout(self.server, template_name="local", classes="h-100"):
63+
vtklocal.LocalView(
64+
self.render_window,
65+
ctx_name="local",
66+
throttle_rate=20,
67+
camera="local_camera = $event",
68+
ref="wasm", # to allow JS method call
69+
)
70+
# -----------------------------------------------------------------
71+
# vtk 9.6 seems to have a sizing issue with WASM which I tried to
72+
# fix by calling a resize() locally but that didn't help.
73+
# -----------------------------------------------------------------
74+
# client.ClientTriggers(mounted="utils.get('Vue').nextTick(trame.refs.wasm.resize)")
75+
# -----------------------------------------------------------------
76+
77+
# Remote Rendering
78+
with DivLayout(self.server, template_name="remote", classes="h-100"):
79+
view = rca.RemoteControlledArea(display="image")
80+
self.ctx.remote = view.create_view_handler(
81+
self.render_window, encoder="turbo-jpeg"
82+
)
83+
84+
# Main UI
85+
with VAppLayout(self.server) as self.ui:
86+
# Switch between rendering UI
87+
client.ServerTemplate(name=("rendering_mode", "local"))
88+
89+
# Controller UI
90+
with v3.VCard(style=OVERLAY, classes="pa-2"):
91+
with v3.VBtnToggle(
92+
v_model="rendering_mode",
93+
group=True,
94+
mandatory=True,
95+
density="compact",
96+
):
97+
for name in ["Local", "Remote"]:
98+
v3.VBtn(
99+
text=name,
100+
value=name.lower(),
101+
density="compact",
102+
classes="text-none",
103+
)
104+
105+
v3.VSlider(
106+
v_model=("resolution", 6),
107+
min=3,
108+
max=30,
109+
step=1,
110+
hide_details=True,
111+
density="comfortable",
112+
)
113+
114+
@change("resolution", "rendering_mode")
115+
def _on_resolution(self, resolution, rendering_mode, **_):
116+
self.cone.resolution = resolution
117+
self.ctx[rendering_mode].update()
118+
119+
@change("local_camera")
120+
def _on_camera_sync(self, local_camera, **_):
121+
if local_camera:
122+
self.ctx.local.vtk_update_from_state(local_camera)
123+
124+
125+
def main():
126+
app = ClientRemoteRendering()
127+
app.server.start()
128+
129+
130+
if __name__ == "__main__":
131+
main()

0 commit comments

Comments
 (0)