Skip to content

Viewer State & Events

Panopti offers various mechanisms for reading and modifying the viewer's state.

Geometry

All geometric objects support the following get, update, delete functions:

import panopti
viewer = panopti.connect(...)
viewer.add_mesh(name='MyMesh', ...)

# Get mesh:
mymesh = viewer.get('MyMesh')

# Update mesh vertices, vertex_colors, or any other attributes:
mymesh.update(vertices=..., vertex_colors=...)

# Delete mesh:
mymesh.delete()

Camera

See also: Camera

You can directly get and set camera attributes by doing:

import panopti
viewer = panopti.connect(...)

# get current camera state as dict
camera_data = viewer.camera()

# set camera attributes manually
viewer.set_camera(
    position=(0.0, 5.0, 0.0),
    target=(0.0, 0.0, 0.0),
    projection_mode='orthographic'
)

# standard look_at function:
viewer.look_at(
    position=(-2.0, 1.0, 3.0),
    target=(0.0, -2.0, 0.0),
)

@viewer.events.camera()
def my_camera_event(viewer, camera_info):
    # this function is triggered when the viewer camera is manipulated
    print('Camera was moved to ', camera_info.position)

viewer.hold()

ViewerClient.camera()

camera

Return the current camera parameters as a dictionary containing:

key meaning type
position camera world coords ndarray
rotation camera XYZ euler rotation ndarray
quaternion camera rotation as quaternion ndarray
up camera up-vector ndarray
target point the camera is looking at ndarray
fov vertical field-of-view (degrees) float
near near-plane distance float
far far-plane distance float
aspect viewport aspect ratio (w / h) float
projection_mode 'perspective' or 'orthographic' str
ViewerClient.set_camera()

set_camera

Update the viewer camera.

Accepts the same keyword arguments that camera returns. Any provided values will overwrite the current camera state.

ViewerClient.look_at()

look_at

Position the camera and look at target.

Parameters:

Name Type Description Default
position (list, ndarray)

Camera position in world coordinates.

required
target (list, ndarray)

World coordinate the camera should look at.

required
@viewer.events.camera()

event decorator

The camera event is triggered when the user manipulates the viewer camera (e.g. orbit, pan, zoom). This event provides a CameraInfo object containing information about the camera's current state.

Parameters:

Name Type Description Default
throttle int

Throttle interval in milliseconds. If provided, the callback will only be called at most once per throttle interval.

None

Example usage:

@viewer.events.camera()
def camera_event(viewer, camera_info):
    print('Camera was updated!')
    # swivel scene mesh to always face the camera (in Y-axis):
    mesh = viewer.get('myMesh')
    mx, my, mz = mesh.position
    cx, cy, cz = camera_info.position  # dot-access notation
    yaw = math.atan2(cx - mx, cz - mz)
    mesh.rotation = [0, yaw, 0]
    mesh.update(rotation=[0, yaw, 0])

# Or with throttling (100ms interval)
@viewer.events.camera(throttle=100)
def throttled_camera_event(viewer, camera_info):
    print('Throttled camera update!')
camera_info is a CameraInfo object with the following attributes:

attribute meaning type
position camera world coords ndarray
rotation camera XYZ euler rotation ndarray
quaternion camera rotation as quaternion ndarray
up camera up-vector ndarray
target point the camera is looking at ndarray
fov vertical field-of-view (degrees) float
near near-plane distance float
far far-plane distance float
aspect viewport aspect ratio (w / h) float
projection_mode 'perspective' or 'orthographic' str

Transformations

See also: Transformations & Gizmo

Panopti offers interactive mechanisms for translating, rotating, and scaling geometries through the transformation panel and through gizmos. To open the transformation panel, simply select a scene object. For the gizmo tool, see the toolbar. The transformated state of scene objects can be accessed by your code through property fields of scene geometries.

Example:

import panopti
import numpy as np
viewer = panopti.connect(server_url="http://localhost:8080", viewer_id="client")

# ... load triangle mesh vertices / faces ...

viewer.add_mesh(vertices=vertices, faces=faces, name="MyMesh")

# Add a button that reads off the mesh's current transformation:
def my_button_callback(viewer):
    mesh = viewer.get('MyMesh')

    # request MyMesh's 4x4 transformation matrix:
    trans_mat = mesh.trans_mat

    # or directly access the transformed vertex tensor:
    transformed_verts = mesh.viewer_verts

    # ... do something here ...

viewer.button(callback=my_button_callback, name='MyButton')

viewer.hold() # prevent script from terminating

Each geometry type exposes helper attributes for retrieving the object's current 4x4 transformation matrix and associated quantities. For example, for Meshes and AnimatedMeshes objects, we offer:

Mesh.trans_mat
trans_mat

Fetches the objects current 4x4 transformation matrix.

viewer.get('MyObject').trans_mat

Mesh.viewer_verts
viewer_verts

Fetches the objects current vertices with trans_mat pre-applied

viewer.get('MyObject').viewer_verts

See other geometry types for related functions, e.g. Points.

Events

Panopti exposes several event callbacks through Python decorators, which are accessible through viewer.events, the usage pattern looks like:

import panopti
viewer = panopti.connect(server_url="http://localhost:8080", viewer_id='client')

@viewer.events.camera()
def my_camera_event(viewer, camera_info):
    # this function is triggered when the viewer camera is manipulated
    ...
These callbacks give user code access to various viewer events, see Events for a list of supported decorators.