From 424db4b3e492a5a9e51c8b62b75ded2f6ef9b1cb Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Tue, 31 Jan 2023 12:20:25 -0800 Subject: [PATCH] Ensure view matrix is not computed more than it needs to be --- manimlib/camera/camera_frame.py | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/manimlib/camera/camera_frame.py b/manimlib/camera/camera_frame.py index 9c01af73..e0bc120b 100644 --- a/manimlib/camera/camera_frame.py +++ b/manimlib/camera/camera_frame.py @@ -29,6 +29,9 @@ class CameraFrame(Mobject): ): super().__init__(**kwargs) + self.uniforms["orientation"] = Rotation.identity().as_quat() + self.uniforms["fovy"] = fovy + self.view_matrix = np.identity(4) self.default_orientation = Rotation.identity() @@ -36,8 +39,10 @@ class CameraFrame(Mobject): self.set_width(frame_shape[0], stretch=True) self.set_height(frame_shape[1], stretch=True) self.move_to(center_point) - self.uniforms["orientation"] = Rotation.identity().as_quat() - self.uniforms["fovy"] = fovy + + def note_changed_data(self, recurse_up: bool = True): + super().note_changed_data(recurse_up) + self.get_view_matrix(refresh=True) def set_orientation(self, rotation: Rotation): self.uniforms["orientation"][:] = rotation.as_quat() @@ -77,20 +82,32 @@ class CameraFrame(Mobject): def get_inverse_camera_rotation_matrix(self): return self.get_orientation().as_matrix().T - def get_view_matrix(self): + def get_view_matrix(self, refresh=False): """ Returns a 4x4 for the affine transformation mapping a point into the camera's internal coordinate system """ - shift = Matrix44.from_translation(-self.get_center()).T - rotation = Matrix44.from_quaternion(self.uniforms["orientation"]).T - scale = Matrix44(np.identity(3) / self.get_scale()) - self.view_matrix[:] = shift * rotation * scale + if refresh: + shift = np.identity(4) + rotation = np.identity(4) + scale = np.identity(4) + + shift[:3, 3] = -self.get_center() + rotation[:3, :3] = self.get_inverse_camera_rotation_matrix() + scale[:3, :3] /= self.get_scale() + + self.view_matrix = np.dot(scale, np.dot(rotation, shift)) + return self.view_matrix def get_inv_view_matrix(self): return np.linalg.inv(self.get_view_matrix()) + def interpolate(self, *args, **kwargs): + super().interpolate(*args, **kwargs) + self.get_view_matrix(refresh=True) + + @Mobject.affects_data def rotate(self, angle: float, axis: np.ndarray = OUT, **kwargs): rot = Rotation.from_rotvec(angle * normalize(axis)) self.set_orientation(rot * self.get_orientation())