feat: 运动相机支持 + move_camera.txt 关键帧驱动
input.txt 新增: move_camera: 0 # 0=固定视角, 1=按 move_camera.txt 运动 move_camera.txt 格式(4列:帧号 距离 俯仰角 方位角): 0 40.0 0 0 100 80.0 -30 180 200 40.0 0 360 display.txt header 传递 camera_keyframes JSON 数组, draw.py 按帧时间线性插值驱动相机运动(循环播放)。
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from vispy import app, scene
|
||||
@@ -554,9 +555,45 @@ print(f"[draw] 渲染方式: {mode_str}")
|
||||
print(f"[draw] 绘图参数: ball_radius={ball_radius}, box_color=({box_color_r:.2f},{box_color_g:.2f},{box_color_b:.2f}), alpha={alpha_list}")
|
||||
|
||||
|
||||
# 运动相机关键帧(可选)
|
||||
_CAM_KF = json.loads(h.get("camera_keyframes", "null")) if h.get("camera_keyframes") else None
|
||||
|
||||
|
||||
# ===========================================================================
|
||||
# 每帧回调:仅推进帧索引,从预存数组读取位置,零物理计算
|
||||
# ===========================================================================
|
||||
def _interp_camera(f_idx):
|
||||
"""根据关键帧插值相机位置。"""
|
||||
if not _CAM_KF or len(_CAM_KF) < 2:
|
||||
return
|
||||
# 找到当前帧对应的关键帧区间
|
||||
n_kf = len(_CAM_KF)
|
||||
# 映射到关键帧时间线
|
||||
total_kf_frames = _CAM_KF[-1][0]
|
||||
if total_kf_frames <= 0:
|
||||
return
|
||||
# 循环播放关键帧
|
||||
t = (f_idx / N_FRAMES) * total_kf_frames
|
||||
# 二分查找区间
|
||||
lo, hi = 0, n_kf - 1
|
||||
while hi - lo > 1:
|
||||
mid = (lo + hi) // 2
|
||||
if _CAM_KF[mid][0] <= t:
|
||||
lo = mid
|
||||
else:
|
||||
hi = mid
|
||||
f0, f1 = _CAM_KF[lo], _CAM_KF[hi]
|
||||
if f1[0] - f0[0] == 0:
|
||||
return
|
||||
frac = (t - f0[0]) / (f1[0] - f0[0])
|
||||
dist = f0[1] + (f1[1] - f0[1]) * frac
|
||||
elev = f0[2] + (f1[2] - f0[2]) * frac
|
||||
azim = f0[3] + (f1[3] - f0[3]) * frac
|
||||
view.camera.distance = dist
|
||||
view.camera.elevation = elev
|
||||
view.camera.azimuth = azim
|
||||
|
||||
|
||||
def update(event):
|
||||
global frame_idx
|
||||
frame_idx = (frame_idx + 1) % N_FRAMES # 循环播放
|
||||
@@ -568,6 +605,9 @@ def update(event):
|
||||
if bond_lines is not None and len(BOND_PAIRS) > 0:
|
||||
_update_bond_positions(frame_idx)
|
||||
|
||||
# 运动相机:按关键帧插值
|
||||
_interp_camera(frame_idx)
|
||||
|
||||
# 信息面板显示 plot_atom 的数据
|
||||
x = float(DISP_X[frame_idx])
|
||||
y = float(DISP_Y[frame_idx])
|
||||
|
||||
Reference in New Issue
Block a user