# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, diui.scenelosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
#
__all__ = ['SimpleWindow']
import omni.ui as ui
from pxr import Gf
from omni.kit.manipulator.camera.manipulator import CameraManipulatorBase, SceneViewCameraManipulator, adjust_center_of_interest
def _flatten_matrix(matrix: Gf.Matrix4d):
return [matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],
matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],
matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],
matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]]
class SimpleGrid():
def __init__(self, lineCount: float = 100, lineStep: float = 10, thicknes: float = 1, color: ui.color = ui.color(0.25)):
self.__transform = ui.scene.Transform()
with self.__transform:
for i in range(lineCount * 2 + 1):
ui.scene.Line(
((i - lineCount) * lineStep, 0, -lineCount * lineStep),
((i - lineCount) * lineStep, 0, lineCount * lineStep),
color=color, thickness=thicknes,
)
ui.scene.Line(
(-lineCount * lineStep, 0, (i - lineCount) * lineStep),
(lineCount * lineStep, 0, (i - lineCount) * lineStep),
color=color, thickness=thicknes,
)
class SimpleOrigin():
def __init__(self, length: float = 5, thickness: float = 4):
origin = (0, 0, 0)
with ui.scene.Transform():
ui.scene.Line(origin, (length, 0, 0), color=ui.color.red, thickness=thickness)
ui.scene.Line(origin, (0, length, 0), color=ui.color.green, thickness=thickness)
ui.scene.Line(origin, (0, 0, length), color=ui.color.blue, thickness=thickness)
# Create a few scenes with different camera-maniupulators (a general ui.scene manip and one that allows ortho-tumble )
class SimpleScene:
def __init__(self, custom: bool = False, ortho: bool = False, *args, **kwargs):
self.__scene_view = ui.scene.SceneView(*args, **kwargs)
if ortho:
view = [-1.0, -2.719262146893781e-32, -1.224646799147353e-16, 0.0, -1.2246467991473532e-16, 2.220446049250312e-16, 0.9999999999999998, 0.0, 0.0, 0.9999999999999998, -2.220446049250312e-16, 0.0, 0, 0, -2000, 1.0]
projection = [0.0022443845736905463, 0.0, 0.0, 0.0, 0.0, 0.004, 0.0, 0.0, 0.0, 0.0, -2.000002000002e-06, 0.0, -0.0, -0.0, -1.000002000002, 1.0]
else:
view = [0.7071067811865476, -0.40557978767263897, 0.5792279653395693, 0.0, -2.775557561562892e-17, 0.8191520442889919, 0.5735764363510462, 0.0, -0.7071067811865477, -0.4055797876726389, 0.5792279653395692, 0.0, 6.838973831690966e-14, -3.996234471857009, -866.0161835150924, 1.0000000000000002]
projection = [4.7602203407949375, 0.0, 0.0, 0.0, 0.0, 8.483787309173106, 0.0, 0.0, 0.0, 0.0, -1.000002000002, -1.0, 0.0, 0.0, -2.000002000002, 0.0]
view = Gf.Matrix4d(*view)
center_of_interest = [0, 0, -view.Transform((0, 0, 0)).GetLength()]
with self.__scene_view.scene:
self.items = [SimpleGrid(), ui.scene.Arc(100, axis=1, wireframe=True), SimpleOrigin()]
if custom:
self.items.append(CameraManipulatorBase())
else:
self.items.append(SceneViewCameraManipulator(center_of_interest))
# Push the start values into the CameraManipulator
self.setup_camera_model(self.items[-1].model, view, projection, center_of_interest, ortho)
def setup_camera_model(self, cam_model, view, projection, center_of_interest, ortho):
cam_model.set_floats('transform', _flatten_matrix(view.GetInverse()))
cam_model.set_floats('projection', projection)
cam_model.set_floats('center_of_interest', [0, 0, -view.Transform((0, 0, 0)).GetLength()])
if ortho:
cam_model.set_ints('orthographic', [ortho])
# Setup up the subscription to the CameraModel so changes here get pushed to SceneView
self.model_changed_sub = cam_model.subscribe_item_changed_fn(self.model_changed)
# And pusht the view and projection into the SceneView.model
cam_model._item_changed(cam_model.get_item('transform'))
cam_model._item_changed(cam_model.get_item('projection'))
def model_changed(self, model, item):
if item == model.get_item('transform'):
transform = Gf.Matrix4d(*model.get_as_floats(item))
# Signal that this this is the final change block, adjust our center-of-interest then
interaction_ended = model.get_as_ints('interaction_ended')
if interaction_ended and interaction_ended[0]:
transform = Gf.Matrix4d(*model.get_as_floats(item))
# Adjust the center-of-interest if requested (zoom out in perspective does this)
initial_transform = Gf.Matrix4d(*model.get_as_floats('initial_transform'))
coi_start, coi_end = adjust_center_of_interest(model, initial_transform, transform)
if coi_end:
model.set_floats('center_of_interest', [coi_end[0], coi_end[1], coi_end[2]])
# Push the start values into the SceneView
self.__scene_view.model.set_floats('view', _flatten_matrix(transform.GetInverse()))
elif item == model.get_item('projection'):
self.__scene_view.model.set_floats('projection', model.get_as_floats('projection'))
class SimpleWindow(ui.Window):
def __init__(self, name: str, custom=False, ortho: bool = False):
super().__init__(f'{name} Camera Manipulator', width=640, height=480 + 20, flags=ui.WINDOW_FLAGS_NO_SCROLLBAR)
self.frame.set_style({"Window": {"background_color": 0xff000000}})
with self.frame:
self.__scene_view = SimpleScene(custom, ortho)
def destroy(self):
if self.__scene_view:
self.__scene_view.destroy()
super().destroy()
persp_win = SimpleWindow('Perspective')
ortho_win = SimpleWindow('Orthographic', ortho=True)
ortho_custom_win = SimpleWindow('Custom Orthographic', custom=True, ortho=True)