Camera Manipulator
Mouse interaction with the Viewport is handled with classes from omni.kit.manipulator.camera
, which is built on top of the omni.ui.scene
framework.
We’ve created an omni.ui.scene.SceneView
to host the manipulator, and by simply assigning the camera manipulators model
into the SceneView’s model, all of the edits to the Camera’s transform will be pushed through to the SceneView
.
# And finally add the camera-manipulator into that view
with self.__scene_view.scene:
self.__camera_manip = ViewportCameraManipulator(self.viewport_api)
# Push the camera manipulator's model into the SceneView so it'lll auto-update
self.__scene_view.model = self.__camera_manip.model
The omni.ui.scene.SceneView
only understands two values: ‘view’ and ‘projection’. Our CameraManipulator’s model will push
out those values as edits are made; however, it supports a larger set of values to control the manipulator itself.
Operations and Values
The CameraManipulator model store’s the amount of movement according to three modes, applied in this order:
Tumble
Look
Move (Pan)
Fly (FlightMode / WASD navigation)
tumble
Tumble values are specified in degrees as the amount to rotate around the current up-axis. These values should be pre-scaled with any speed before setting into the model. This allows for different manipulators/gestures to interpret speed differently, rather than lock to a constant speed.
# Tumble by 180 degrees around Y (as a movement across ui X would cause)
model.set_floats('tumble', [0, 180, 0])
look
Look values are specified in degrees as the amount to rotate around the current up-axis. These values should be pre-scaled with any speed before setting into the model. This allows for different manipulators/gestures to interpret speed differently, rather than lock to a constant speed.
# Look by 90 degrees around X (as a movement across ui Y would cause)
# i.e Look straight up
model.set_floats('look', [90, 0, 0])
move
Move values are specified in world units and the amount to move the camera by. Move is applied after rotation, so the X, Y, Z are essentially left, right, back. These values should be pre-scaled with any speed before setting into the model. This allows for different manipulators/gestures to interpret speed differently, rather than lock to a constant speed.
# Move left by 30 units, up by 60 and back by 90
model.set_floats('move', [30, 60, 90])
fly
Fly values are the direction of flight in X, Y, Z.
Fly is applied after rotation, so the X, Y, Z are essentially left, right, back.
These values will be scaled with fly_speed
before aplication.
Because fly is a direction with fly_speed
automatically applied, if a gesture/manipulator wants to fly slower
without changing fly_speed
globally, it must apply whatever factor is required before setting.
# Move left
model.set_floats('fly', [1, 0, 0])
# Move up
model.set_floats('fly', [0, 1, 0])
Speed
By default the Camera manipulator will map a full mouse move across the viewport as follows:
Pan: A full translation of the center-of-interest across the Viewport.
Tumble: A 180 degree rotation across X or Y.
Look: A 180 degree rotation across X and a 90 degree rotation across Y.
These speed can be adjusted by setting float values into the model.
world_speed
The Pan and Zoom speed can be adjusted with three floats set into the model as ‘world_speed’.
# Half the movement speed for both Pan and Zoom
pan_speed_x = 0.5, pan_speed_y = 0.5, zoom_speed_z = 0.5
model.set_floats('world_speed', [pan_speed_x, pan_speed_y, zoom_speed_z])
rotation_speed
The Tumble and Look speed can be adjusted with either a scalar value for all rotation axes or per component.
# Half the rotation speed for both Tumble and Look
rot_speed_both = 0.5
model.set_floats('rotation_speed', [rot_speed_both])
# Half the rotation speed for both Tumble and Look in X and quarter if for Y
rot_speed_x = 0.5, rot_speed_y = 0.25
model.set_floats('rotation_speed', [rot_speed_x, rot_speed_y])
tumble_speed
Tumble can be adjusted separately with either a scalar value for all rotation axes or per component.
The final speed of Tumble operation is rotation_speed * tumble_speed
# Half the rotation speed for Tumble
rot_speed_both = 0.5
model.set_floats('tumble_speed', [rot_speed_both])
# Half the rotation speed for Tumble in X and quarter if for Y
rot_speed_x = 0.5, rot_speed_y = 0.25
model.set_floats('tumble_speed', [rot_speed_x, rot_speed_y])
look_speed
Look can be adjusted separately with either a scalar value for all rotation axes or per component.
The final speed of a Look operation is rotation_speed * tumble_speed
# Half the rotation speed for Look
rot_speed_both = 0.5
model.set_floats('look_speed', [rot_speed_both])
# Half the rotation speed for Tumble in X and quarter if for Y
rot_speed_x = 0.5, rot_speed_y = 0.25
model.set_floats('look_speed', [rot_speed_x, rot_speed_y])
fly_speed
The speed at which FlightMode (WASD navigation) will fly through the scene. FlightMode speed can be adjusted separately with either a scalar value for all axes or per component.
# Half the speed in all directions
fly_speed = 0.5
model.set_floats('fly_speed', [fly_speed])
# Half the speed when moving in X or Y, but double it moving in Z
fly_speed_x_y = 0.5, fly_speed_z = 2
model.set_floats('fly_speed', [fly_speed_x_y, fly_speed_x_y, fly_speed_z])
Undo
Because we’re operating on a unique omni.usd.UsdContext
we don’t want movement in the preview-window to affect the undo-stack.
To accomplish that, we’ll set the ‘disable_undo’ value to an array of 1 int; essentially saying disable_undo=True
.
# Let's disable any undo for these movements as we're a preview-window
model.set_ints('disable_undo', [1])
Disabling operations
By default the manipulator will allow Pan, Zoom, Tumble, and Look operations on a perspective camera, but only allow Pan and Zoom on an orthographic one. If we want to explicitly disable any operations again we set int values as booleans into the model.
disable_tumble
# Disable the Tumble manipulation
model.set_ints('disable_tumble', [1])
disable_look
# Disable the Look manipulation
model.set_ints('disable_look', [1])
disable_pan
# Disable the Pan manipulation.
model.set_ints('disable_pan', [1])
disable_zoom
# Disable the Zoom manipulation.
model.set_ints('disable_zoom', [1])