Interpolate keyframes to get camera at any frame.
(self, frame_idx: int)
| 183 | }) |
| 184 | |
| 185 | def get_camera(self, frame_idx: int) -> Camera: |
| 186 | """Interpolate keyframes to get camera at any frame.""" |
| 187 | if not self.keyframes: |
| 188 | return Camera([0, 0, 0], [0, 0, 1], [0, 1, 0]) |
| 189 | |
| 190 | # Clamp |
| 191 | frame_idx = max(0, min(frame_idx, self.total_frames - 1)) |
| 192 | |
| 193 | # Find surrounding keyframes |
| 194 | right_idx = 0 |
| 195 | for i, kf in enumerate(self.keyframes): |
| 196 | if kf['frame'] > frame_idx: |
| 197 | right_idx = i |
| 198 | break |
| 199 | else: |
| 200 | # frame_idx >= last keyframe |
| 201 | kf = self.keyframes[-1] |
| 202 | return Camera(kf['eye'], kf['center'], kf['up'], kf['fov']) |
| 203 | |
| 204 | if right_idx == 0: |
| 205 | # frame_idx <= first keyframe |
| 206 | kf = self.keyframes[0] |
| 207 | return Camera(kf['eye'], kf['center'], kf['up'], kf['fov']) |
| 208 | |
| 209 | left_kf = self.keyframes[right_idx - 1] |
| 210 | right_kf = self.keyframes[right_idx] |
| 211 | |
| 212 | # Compute interpolation parameter |
| 213 | span = right_kf['frame'] - left_kf['frame'] |
| 214 | if span == 0: |
| 215 | t = 0.0 |
| 216 | else: |
| 217 | t = (frame_idx - left_kf['frame']) / span |
| 218 | |
| 219 | if self.interpolation == 'smoothstep': |
| 220 | t = _smoothstep(t) |
| 221 | |
| 222 | cam_a = Camera(left_kf['eye'], left_kf['center'], left_kf['up'], left_kf['fov']) |
| 223 | cam_b = Camera(right_kf['eye'], right_kf['center'], right_kf['up'], right_kf['fov']) |
| 224 | return _lerp_camera(cam_a, cam_b, t) |
| 225 | |
| 226 | def __len__(self) -> int: |
| 227 | return self.total_frames |
no test coverage detected