From 811c21666a4f4432461999a81be0639dc63a93bd Mon Sep 17 00:00:00 2001 From: Dario Mylonopoulos Date: Sat, 2 Sep 2023 15:42:59 +0200 Subject: [PATCH] Z up config option --- aitviewer/aitvconfig.yaml | 3 +++ aitviewer/renderables/plane.py | 4 ++-- aitviewer/renderables/point_clouds.py | 3 ++- aitviewer/renderables/smpl.py | 2 +- aitviewer/scene/camera.py | 17 +++++++++++------ aitviewer/scene/scene.py | 13 ++++++++----- 6 files changed, 27 insertions(+), 15 deletions(-) diff --git a/aitviewer/aitvconfig.yaml b/aitviewer/aitvconfig.yaml index 5ca1658..283f25d 100644 --- a/aitviewer/aitvconfig.yaml +++ b/aitviewer/aitvconfig.yaml @@ -36,6 +36,9 @@ backface_culling: True background_color: [1.0, 1.0, 1.0, 1.0] window_type: "pyqt5" +# Viewer defaults to Y up, set to true for Z up. +z_up: False + # Server for remote connections. server_enabled: False server_port: 8417 diff --git a/aitviewer/renderables/plane.py b/aitviewer/renderables/plane.py index 077f0ac..2be3c81 100644 --- a/aitviewer/renderables/plane.py +++ b/aitviewer/renderables/plane.py @@ -172,8 +172,8 @@ def __init__( v1 = np.array([1, 0, 0], dtype=np.float32) v2 = np.array([0, 0, 1], dtype=np.float32) elif plane == "xy": - v1 = np.array([1, 0, 0], dtype=np.float32) - v2 = np.array([0, 1, 0], dtype=np.float32) + v1 = np.array([0, 1, 0], dtype=np.float32) + v2 = np.array([1, 0, 0], dtype=np.float32) else: # plane == "yz" v1 = np.array([0, 1, 0], dtype=np.float32) diff --git a/aitviewer/renderables/point_clouds.py b/aitviewer/renderables/point_clouds.py index 7c2526e..dac1e3f 100644 --- a/aitviewer/renderables/point_clouds.py +++ b/aitviewer/renderables/point_clouds.py @@ -3,6 +3,7 @@ import numpy as np from moderngl_window.opengl.vao import VAO +from aitviewer.configuration import CONFIG as C from aitviewer.scene.node import Node from aitviewer.shaders import ( get_fragmap_program, @@ -54,7 +55,7 @@ def __init__( self.vao = VAO("points", mode=moderngl.POINTS) - if z_up: + if z_up and not C.z_up: self.rotation = np.matmul(np.array([[1, 0, 0], [0, 0, 1], [0, -1, 0]]), self.rotation) @property diff --git a/aitviewer/renderables/smpl.py b/aitviewer/renderables/smpl.py index 0a789df..4020ff0 100644 --- a/aitviewer/renderables/smpl.py +++ b/aitviewer/renderables/smpl.py @@ -166,7 +166,7 @@ def __init__( else: global_oris = np.tile(np.eye(3), self.joints.shape[:-1])[np.newaxis] - if self._z_up: + if self._z_up and not C.z_up: self.rotation = np.matmul(np.array([[1, 0, 0], [0, 0, 1], [0, -1, 0]]), self.rotation) self.rbs = RigidBodies(self.joints, global_oris, length=0.1, gui_affine=False, name="Joint Angles") diff --git a/aitviewer/scene/camera.py b/aitviewer/scene/camera.py index f797416..09de21d 100644 --- a/aitviewer/scene/camera.py +++ b/aitviewer/scene/camera.py @@ -712,6 +712,7 @@ def __init__( cols, rows, fov=45, + world_up=None, near=None, far=None, viewer=None, @@ -723,7 +724,11 @@ def __init__( positions.shape[0] == 1 or targets.shape[0] == 1 or positions.shape[0] == targets.shape[0] ), f"position and target array shape mismatch: {positions.shape} and {targets.shape}" - self._world_up = np.array([0.0, 1.0, 0.0]) + if world_up: + self._world_up = world_up + else: + self._world_up = np.array([0.0, 0.0, 1.0]) if C.z_up else np.array([0.0, 1.0, 0.0]) + self._targets = targets super(PinholeCamera, self).__init__(position=position, n_frames=targets.shape[0], viewer=viewer, **kwargs) @@ -862,9 +867,9 @@ def __init__(self, fov=45, orthographic=None, znear=None, zfar=None): self.ortho_size = 1.0 if orthographic is None else orthographic # Default camera settings. - self._position = np.array([0.0, 0.0, 2.5]) + self._position = np.array([0.0, 2.5, 0.0]) if C.z_up else np.array([0.0, 0.0, 2.5]) self._target = np.array([0.0, 0.0, 0.0]) - self._up = np.array([0.0, 1.0, 0.0]) + self._up = np.array([0.0, 0.0, 1.0]) if C.z_up else np.array([0.0, 1.0, 0.0]) self.ZOOM_FACTOR = 4 self.ROT_FACTOR = 0.0025 @@ -904,7 +909,7 @@ def control_mode(self, mode): if mode not in self._control_modes: raise ValueError(f"Invalid camera mode: {mode}") if mode == "first_person" or mode == "turntable": - self.up = (0, 1, 0) + self.up = (0, 0, 1) if C.z_up else (0, 1, 0) self._control_mode = mode def copy(self): @@ -1052,8 +1057,8 @@ def rotate_azimuth(self, angle): if np.abs(angle) < 1e-8: return cam_pose = np.linalg.inv(self.view_matrix) - y_axis = cam_pose[:3, 1] - rot = rotation_matrix(angle, y_axis, self.target) + up_axis = cam_pose[:3, 1] + rot = rotation_matrix(angle, up_axis, self.target) self.position = _transform_vector(rot, self.position) def _rotation_from_mouse_delta(self, mouse_dx: int, mouse_dy: int): diff --git a/aitviewer/scene/scene.py b/aitviewer/scene/scene.py index 4f3e9dd..8ccb3f7 100644 --- a/aitviewer/scene/scene.py +++ b/aitviewer/scene/scene.py @@ -42,7 +42,7 @@ def __init__(self, **kwargs): Light.facing_origin( light_color=(1.0, 1.0, 1.0), name="Back Light", - position=(0.0, 10.0, -15.0), + position=(0.0, -15.0, 10.0) if C.z_up else (0.0, 10.0, -15.0), shadow_enabled=False, ) ) @@ -50,7 +50,7 @@ def __init__(self, **kwargs): Light.facing_origin( light_color=(1.0, 1.0, 1.0), name="Front Light", - position=(0.0, 10.0, 15.0), + position=(0.0, 15.0, 10.0) if C.z_up else (0.0, 10.0, 15.0), ) ) self.add(*self.lights) @@ -61,7 +61,9 @@ def __init__(self, **kwargs): self.origin = CoordinateSystem(name="Origin", length=0.1, gui_affine=False, gui_material=False) self.add(self.origin) - self.floor = ChessboardPlane(100.0, 200, (0.9, 0.9, 0.9, 1.0), (0.82, 0.82, 0.82, 1.0), name="Floor") + self.floor = ChessboardPlane( + 100.0, 200, (0.9, 0.9, 0.9, 1.0), (0.82, 0.82, 0.82, 1.0), "xy" if C.z_up else "xz", name="Floor" + ) self.floor.material.diffuse = 0.1 self.add(self.floor) @@ -233,8 +235,9 @@ def bounds_without_floor(self): def auto_set_floor(self): """Finds the minimum lower bound in the y coordinate from all the children bounds and uses that as the floor""" if self.floor is not None and len(self.nodes) > 0: - self.floor.position[1] = self.current_bounds[1, 0] - self.floor.update_transform() + axis = 2 if C.z_up else 1 + self.floor.position[axis] = self.current_bounds[axis, 0] + self.floor.update_transform(parent_transform=self.model_matrix) def auto_set_camera_target(self): """Sets the camera target to the average of the center of all objects in the scene"""