@@ -103,6 +103,13 @@ def location(self, location: np.ndarray) -> None:
103103 sky = self ._sky ,
104104 )
105105
106+ @property
107+ def orientation (self ) -> np .ndarray :
108+ """
109+ Return the current orientation of the camera.
110+ """
111+ return np .array (self ._camera .matrix_world )[:3 , :3 ]
112+
106113 @property
107114 def look_at (self ) -> Optional [np .ndarray ]:
108115 """
@@ -170,12 +177,40 @@ def compute_matrix_world(
170177
171178 direction = direction / np .linalg .norm (direction )
172179 right = np .cross (direction , sky )
180+ right = right / np .linalg .norm (right )
173181 up = np .cross (right , direction )
174-
175182 return np .array (
176183 [[* right , 0.0 ], [* up , 0.0 ], [* (- direction ), 0.0 ], [* location , 1.0 ]]
177184 )
178185
186+ def rotate (self , angle : float ) -> None :
187+ """
188+ Rotate the camera around the look-at-axis.
189+
190+ Parameters
191+ ----------
192+ angle : float
193+ The angle (degree) to rotate the camera.
194+ """
195+ assert isinstance (angle , (int , float )), "angle must be a number"
196+ angle_rad = np .deg2rad (angle )
197+ rotation_matrix = np .array (
198+ [
199+ [np .cos (angle_rad ), - np .sin (angle_rad ), 0 ],
200+ [np .sin (angle_rad ), np .cos (angle_rad ), 0 ],
201+ [0 , 0 , 1 ],
202+ ]
203+ )
204+ orientation = self .orientation @ rotation_matrix
205+ self ._camera .matrix_world = np .array (
206+ [
207+ [* orientation [:, 0 ], 0.0 ],
208+ [* orientation [:, 1 ], 0.0 ],
209+ [* orientation [:, 2 ], 0.0 ],
210+ [* self .location , 1.0 ],
211+ ]
212+ )
213+
179214 def set_resolution (self , width : int , height : int ) -> None :
180215 """
181216 Set the resolution of the camera.
0 commit comments