MCPcopy Create free account
hub / github.com/Robbyant/lingbot-map / KeyframeAnimator

Class KeyframeAnimator

demo_render/interactive_viewer/camera.py:191–268  ·  view source on GitHub ↗

Manages keyframes and produces interpolated camera paths.

Source from the content-addressed store, hash-verified

189
190
191class KeyframeAnimator:
192 """Manages keyframes and produces interpolated camera paths."""
193
194 def __init__(self):
195 self.keyframes: List[Keyframe] = []
196
197 def add(self, camera: OrbitCamera, frame_idx: int = 0):
198 kf = Keyframe(
199 eye=camera.eye.copy(),
200 look_at=camera.look_at.copy(),
201 up=camera.up.copy(),
202 fov_deg=camera.fov_deg,
203 frame_idx=frame_idx,
204 )
205 self.keyframes.append(kf)
206
207 def remove_last(self):
208 if self.keyframes:
209 self.keyframes.pop()
210
211 def clear(self):
212 self.keyframes.clear()
213
214 def interpolate(self, steps_per_segment: int = 60) -> List[Tuple[OrbitCamera, int]]:
215 """Interpolate keyframes with cubic spline. Returns list of (camera, frame_idx)."""
216 if len(self.keyframes) < 2:
217 if self.keyframes:
218 cam = OrbitCamera(
219 self.keyframes[0].eye,
220 self.keyframes[0].look_at,
221 self.keyframes[0].up,
222 self.keyframes[0].fov_deg,
223 )
224 return [(cam, self.keyframes[0].frame_idx)]
225 return []
226
227 from scipy.interpolate import CubicSpline
228
229 n = len(self.keyframes)
230 t_knots = np.linspace(0, 1, n)
231 t_interp = np.linspace(0, 1, (n - 1) * steps_per_segment + 1)
232
233 # Stack all fields
234 eyes = np.array([kf.eye for kf in self.keyframes])
235 look_ats = np.array([kf.look_at for kf in self.keyframes])
236 ups = np.array([kf.up for kf in self.keyframes])
237 fovs = np.array([kf.fov_deg for kf in self.keyframes])
238 frames = np.array([kf.frame_idx for kf in self.keyframes], dtype=np.float64)
239
240 cs_eye = CubicSpline(t_knots, eyes)
241 cs_look = CubicSpline(t_knots, look_ats)
242 cs_up = CubicSpline(t_knots, ups)
243 cs_fov = CubicSpline(t_knots, fovs)
244 cs_frame = CubicSpline(t_knots, frames)
245
246 result = []
247 for t in t_interp:
248 e = cs_eye(t).astype(np.float32)

Callers 1

__init__Method · 0.90

Calls

no outgoing calls

Tested by

no test coverage detected