57def look_at_matrix(eye: tuple[float, float, float], center: tuple[float, float, float], up: tuple[float, float, float]) -> np.ndarray:
58 eye_vector = np.array(eye, dtype=np.float32)
59 center_vector = np.array(center, dtype=np.float32)
60 up_vector = np.array(up, dtype=np.float32)
61 forward = normalize_vector(center_vector - eye_vector)
62 side = normalize_vector(np.cross(forward, up_vector))
63 camera_up = np.cross(side, forward)
64 matrix = identity_matrix()
65 matrix[0, 0] = side[0]
66 matrix[0, 1] = side[1]
67 matrix[0, 2] = side[2]
68 matrix[0, 3] = -float(np.dot(side, eye_vector))
69 matrix[1, 0] = camera_up[0]
70 matrix[1, 1] = camera_up[1]
71 matrix[1, 2] = camera_up[2]
72 matrix[1, 3] = -float(np.dot(camera_up, eye_vector))
73 matrix[2, 0] = -forward[0]
74 matrix[2, 1] = -forward[1]
75 matrix[2, 2] = -forward[2]
76 matrix[2, 3] = float(np.dot(forward, eye_vector))
77 return matrix
78