---
title: utils
---

<div class="python-reference">

<a id="fastvideo.models.dits.matrixgame3.utils"></a>

<h2 id="fastvideo.models.dits.matrixgame3.utils.compute_relative_poses"><code>fastvideo.models.dits.matrixgame3.utils.compute_relative_poses</code></h2>
<pre class="doc-signature"><code>compute_relative_poses(c2ws_mat: torch.Tensor, framewise: bool = False, normalize_trans: bool = True) -&gt; torch.Tensor</code></pre>

<h2 id="fastvideo.models.dits.matrixgame3.utils.get_plucker_embeddings"><code>fastvideo.models.dits.matrixgame3.utils.get_plucker_embeddings</code></h2>
<pre class="doc-signature"><code>get_plucker_embeddings(c2ws_mat: torch.Tensor, Ks: torch.Tensor, height: int, width: int)</code></pre>

<h2 id="fastvideo.models.dits.matrixgame3.utils.interpolate_camera_poses"><code>fastvideo.models.dits.matrixgame3.utils.interpolate_camera_poses</code></h2>
<pre class="doc-signature"><code>interpolate_camera_poses(src_indices: np.ndarray, src_rot_mat: np.ndarray, src_trans_vec: np.ndarray, tgt_indices: np.ndarray) -&gt; torch.Tensor</code></pre>

<h2 id="fastvideo.models.dits.matrixgame3.utils.compute_next_pose_from_action"><code>fastvideo.models.dits.matrixgame3.utils.compute_next_pose_from_action</code></h2>
<pre class="doc-signature"><code>compute_next_pose_from_action(current_pose, keyboard_action, mouse_action)</code></pre>

<details><summary>Source</summary><pre><code>def compute_next_pose_from_action(current_pose, keyboard_action, mouse_action):
    x, y, z, pitch, yaw = current_pose
    w, s, a, d = keyboard_action&#91;:4&#93;
    mouse_x, mouse_y = mouse_action&#91;:2&#93;

    delta_pitch = MOUSE_PITCH_SENSITIVITY * mouse_x if abs(mouse_x) &gt;= MOUSE_THRESHOLD else 0.0
    delta_yaw = MOUSE_YAW_SENSITIVITY * mouse_y if abs(mouse_y) &gt;= MOUSE_THRESHOLD else 0.0
    new_pitch = pitch + delta_pitch
    new_yaw = yaw + delta_yaw

    new_yaw = (new_yaw + 180) % 360 - 180

    local_forward = 0.0
    if w &gt; 0.5 and s &lt; 0.5:
        local_forward = WSAD_OFFSET
    elif s &gt; 0.5 and w &lt; 0.5:
        local_forward = -WSAD_OFFSET

    local_right = 0.0
    if d &gt; 0.5 and a &lt; 0.5:
        local_right = WSAD_OFFSET
    elif a &gt; 0.5 and d &lt; 0.5:
        local_right = -WSAD_OFFSET

    if abs(local_forward) &gt; 0.1 and abs(local_right) &gt; 0.1:
        local_forward = np.sign(local_forward) * DIAGONAL_OFFSET
        local_right = np.sign(local_right) * DIAGONAL_OFFSET

    avg_yaw = float((yaw + new_yaw) / 2.0)
    yaw_rad = float(np.deg2rad(avg_yaw))
    cos_yaw = np.cos(yaw_rad)
    sin_yaw = np.sin(yaw_rad)

    delta_x = cos_yaw * local_forward - sin_yaw * local_right
    delta_y = sin_yaw * local_forward + cos_yaw * local_right
    return np.array(&#91;x + delta_x, y + delta_y, z, new_pitch, new_yaw&#93;, dtype=np.float32)</code></pre></details>
<h2 id="fastvideo.models.dits.matrixgame3.utils.compute_all_poses_from_actions"><code>fastvideo.models.dits.matrixgame3.utils.compute_all_poses_from_actions</code></h2>
<pre class="doc-signature"><code>compute_all_poses_from_actions(keyboard_conditions, mouse_conditions)</code></pre>

<details><summary>Source</summary><pre><code>def compute_all_poses_from_actions(keyboard_conditions, mouse_conditions):
    poses = np.zeros((len(keyboard_conditions), 5), dtype=np.float32)
    for idx in range(len(keyboard_conditions) - 1):
        poses&#91;idx + 1&#93; = compute_next_pose_from_action(poses&#91;idx&#93;, keyboard_conditions&#91;idx&#93;, mouse_conditions&#91;idx&#93;)
    return poses</code></pre></details>
<h2 id="fastvideo.models.dits.matrixgame3.utils.build_intrinsics"><code>fastvideo.models.dits.matrixgame3.utils.build_intrinsics</code></h2>
<pre class="doc-signature"><code>build_intrinsics(height: int, width: int, device: torch.device, dtype: torch.dtype) -&gt; torch.Tensor</code></pre>

<details><summary>Source</summary><pre><code>def build_intrinsics(height: int, width: int, device: torch.device, dtype: torch.dtype) -&gt; torch.Tensor:
    fov_rad = float(np.deg2rad(90.0))
    fx = float(width) / (2.0 * float(np.tan(fov_rad / 2.0)))
    fy = float(height) / (2.0 * float(np.tan(fov_rad / 2.0)))
    return torch.tensor(&#91;&#91;fx, fy, width / 2.0, height / 2.0&#93;&#93;, device=device, dtype=dtype)</code></pre></details>
<h2 id="fastvideo.models.dits.matrixgame3.utils.build_matrixgame3_action_preset"><code>fastvideo.models.dits.matrixgame3.utils.build_matrixgame3_action_preset</code></h2>
<pre class="doc-signature"><code>build_matrixgame3_action_preset(num_frames: int, seed: int | None = None) -&gt; tuple&#91;torch.Tensor, torch.Tensor&#93;</code></pre>

<details><summary>Source</summary><pre><code>def build_matrixgame3_action_preset(num_frames: int, seed: int | None = None) -&gt; tuple&#91;torch.Tensor, torch.Tensor&#93;:
    presets = create_action_presets(num_frames=num_frames, keyboard_dim=6, seed=seed)
    return presets&#91;&quot;keyboard&quot;&#93;, presets&#91;&quot;mouse&quot;&#93;</code></pre></details>
<h2 id="fastvideo.models.dits.matrixgame3.utils.interpolate_camera_poses_handedness"><code>fastvideo.models.dits.matrixgame3.utils.interpolate_camera_poses_handedness</code></h2>
<pre class="doc-signature"><code>interpolate_camera_poses_handedness(src_indices: np.ndarray, src_rot_mat: np.ndarray, src_trans_vec: np.ndarray, tgt_indices: np.ndarray) -&gt; torch.Tensor</code></pre>

<details><summary>Source</summary><pre><code>def interpolate_camera_poses_handedness(
    src_indices: np.ndarray,
    src_rot_mat: np.ndarray,
    src_trans_vec: np.ndarray,
    tgt_indices: np.ndarray,
) -&gt; torch.Tensor:
    dets = np.linalg.det(src_rot_mat)
    flip_handedness = dets.size &gt; 0 and np.median(dets) &lt; 0.0
    if flip_handedness:
        flip_mat = np.diag(&#91;1.0, 1.0, -1.0&#93;).astype(src_rot_mat.dtype)
        src_rot_mat = src_rot_mat @ flip_mat

    c2ws = interpolate_camera_poses(
        src_indices=src_indices,
        src_rot_mat=src_rot_mat,
        src_trans_vec=src_trans_vec,
        tgt_indices=tgt_indices,
    )
    if flip_handedness:
        flip_mat_t = torch.from_numpy(flip_mat).to(c2ws.device, dtype=c2ws.dtype)
        c2ws&#91;:, :3, :3&#93; = c2ws&#91;:, :3, :3&#93; @ flip_mat_t
    return c2ws</code></pre></details>
<h2 id="fastvideo.models.dits.matrixgame3.utils.build_extrinsics_from_actions"><code>fastvideo.models.dits.matrixgame3.utils.build_extrinsics_from_actions</code></h2>
<pre class="doc-signature"><code>build_extrinsics_from_actions(keyboard_conditions: torch.Tensor, mouse_conditions: torch.Tensor) -&gt; torch.Tensor</code></pre>

<details><summary>Source</summary><pre><code>def build_extrinsics_from_actions(
    keyboard_conditions: torch.Tensor,
    mouse_conditions: torch.Tensor,
) -&gt; torch.Tensor:
    keyboard_np = keyboard_conditions.detach().to(dtype=torch.float32).cpu().numpy()
    mouse_np = mouse_conditions.detach().to(dtype=torch.float32).cpu().numpy()
    poses = compute_all_poses_from_actions(keyboard_np, mouse_np)
    rotations = np.concatenate(
        &#91;np.zeros((poses.shape&#91;0&#93;, 1), dtype=np.float32), poses&#91;:, 3:5&#93;&#93;,
        axis=1,
    )
    positions = poses&#91;:, :3&#93;
    return build_extrinsics(rotations, positions)</code></pre></details>
<h2 id="fastvideo.models.dits.matrixgame3.utils.build_extrinsics"><code>fastvideo.models.dits.matrixgame3.utils.build_extrinsics</code></h2>
<pre class="doc-signature"><code>build_extrinsics(video_rotation: np.ndarray, video_position: np.ndarray) -&gt; torch.Tensor</code></pre>

<details><summary>Source</summary><pre><code>def build_extrinsics(
    video_rotation: np.ndarray,
    video_position: np.ndarray,
) -&gt; torch.Tensor:
    extrinsics = &#91;&#93;
    for frame_rotation, frame_position in zip(video_rotation, video_position, strict=False):
        roll_deg, pitch_deg, yaw_deg = frame_rotation
        roll, pitch, yaw = np.radians(&#91;roll_deg, pitch_deg, yaw_deg&#93;)

        rot_z = np.array(
            &#91;&#91;np.cos(yaw), -np.sin(yaw), 0&#93;, &#91;np.sin(yaw), np.cos(yaw), 0&#93;, &#91;0, 0, 1&#93;&#93;,
            dtype=np.float32,
        )
        rot_y = np.array(
            &#91;&#91;np.cos(pitch), 0, np.sin(pitch)&#93;, &#91;0, 1, 0&#93;, &#91;-np.sin(pitch), 0, np.cos(pitch)&#93;&#93;,
            dtype=np.float32,
        )
        rot_x = np.array(
            &#91;&#91;1, 0, 0&#93;, &#91;0, np.cos(roll), -np.sin(roll)&#93;, &#91;0, np.sin(roll), np.cos(roll)&#93;&#93;,
            dtype=np.float32,
        )
        rot = rot_z @ rot_y @ rot_x
        ext = np.eye(4, dtype=np.float32)
        ext&#91;:3, :3&#93; = rot
        ext&#91;:3, 3&#93; = np.asarray(frame_position, dtype=np.float32)
        extrinsics.append(ext)

    r_init = np.array(&#91;&#91;0, 0, 1&#93;, &#91;1, 0, 0&#93;, &#91;0, -1, 0&#93;&#93;, dtype=np.float32)
    extrinsics_tensor = torch.from_numpy(np.stack(extrinsics, axis=0)).float()
    extrinsics_tensor&#91;:, :3, :3&#93; = extrinsics_tensor&#91;:, :3, :3&#93; @ torch.from_numpy(r_init)
    extrinsics_tensor&#91;:, :3, 3&#93; = extrinsics_tensor&#91;:, :3, 3&#93; * 0.01
    return extrinsics_tensor</code></pre></details>
<h2 id="fastvideo.models.dits.matrixgame3.utils.build_plucker_from_c2ws"><code>fastvideo.models.dits.matrixgame3.utils.build_plucker_from_c2ws</code></h2>
<pre class="doc-signature"><code>build_plucker_from_c2ws(c2ws_seq: torch.Tensor, src_indices: np.ndarray, tgt_indices: np.ndarray, *, target_h: int, target_w: int, latent_h: int, latent_w: int, framewise: bool = True) -&gt; torch.Tensor</code></pre>

<details><summary>Source</summary><pre><code>def build_plucker_from_c2ws(
    c2ws_seq: torch.Tensor,
    src_indices: np.ndarray,
    tgt_indices: np.ndarray,
    *,
    target_h: int,
    target_w: int,
    latent_h: int,
    latent_w: int,
    framewise: bool = True,
) -&gt; torch.Tensor:
    c2ws_np = c2ws_seq.detach().to(dtype=torch.float32).cpu().numpy()
    c2ws_infer = interpolate_camera_poses_handedness(
        src_indices=src_indices,
        src_rot_mat=c2ws_np&#91;:, :3, :3&#93;,
        src_trans_vec=c2ws_np&#91;:, :3, 3&#93;,
        tgt_indices=tgt_indices,
    ).to(device=c2ws_seq.device, dtype=c2ws_seq.dtype)
    c2ws_infer = compute_relative_poses(c2ws_infer, framewise=framewise)
    return build_plucker_from_pose(
        c2ws_infer,
        target_h=target_h,
        target_w=target_w,
        latent_h=latent_h,
        latent_w=latent_w,
    )</code></pre></details>
<h2 id="fastvideo.models.dits.matrixgame3.utils.build_plucker_from_pose"><code>fastvideo.models.dits.matrixgame3.utils.build_plucker_from_pose</code></h2>
<pre class="doc-signature"><code>build_plucker_from_pose(c2ws_pose: torch.Tensor, *, target_h: int, target_w: int, latent_h: int, latent_w: int) -&gt; torch.Tensor</code></pre>

<details><summary>Source</summary><pre><code>def build_plucker_from_pose(
    c2ws_pose: torch.Tensor,
    *,
    target_h: int,
    target_w: int,
    latent_h: int,
    latent_w: int,
) -&gt; torch.Tensor:
    ks = build_intrinsics(target_h, target_w, c2ws_pose.device, c2ws_pose.dtype).repeat(c2ws_pose.shape&#91;0&#93;, 1)
    plucker = get_plucker_embeddings(c2ws_pose, ks, target_h, target_w)
    c1 = target_h // latent_h
    c2 = target_w // latent_w
    plucker = plucker.view(c2ws_pose.shape&#91;0&#93;, latent_h, c1, latent_w, c2, 6)
    plucker = plucker.permute(0, 1, 3, 5, 2, 4).reshape(c2ws_pose.shape&#91;0&#93;, latent_h, latent_w, 6 * c1 * c2)
    plucker = plucker.permute(3, 0, 1, 2).unsqueeze(0)
    return plucker</code></pre></details>
<h2 id="fastvideo.models.dits.matrixgame3.utils.select_memory_idx_fov"><code>fastvideo.models.dits.matrixgame3.utils.select_memory_idx_fov</code></h2>
<pre class="doc-signature"><code>select_memory_idx_fov(extrinsics_all: torch.Tensor | np.ndarray, current_start_frame_idx: int, selected_index_base: list&#91;int&#93;, *, height: int = 720, width: int = 1280, return_confidence: bool = False) -&gt; list&#91;int&#93; | tuple&#91;list&#91;int&#93;, list&#91;float&#93;&#93;</code></pre>

<details><summary>Source</summary><pre><code>def select_memory_idx_fov(
    extrinsics_all: torch.Tensor | np.ndarray,
    current_start_frame_idx: int,
    selected_index_base: list&#91;int&#93;,
    *,
    height: int = 720,
    width: int = 1280,
    return_confidence: bool = False,
) -&gt; list&#91;int&#93; | tuple&#91;list&#91;int&#93;, list&#91;float&#93;&#93;:
    if isinstance(extrinsics_all, np.ndarray):
        extrinsics_tensor = torch.from_numpy(extrinsics_all).float()
    else:
        extrinsics_tensor = extrinsics_all.float()

    device = extrinsics_tensor.device
    if current_start_frame_idx &lt;= 1:
        selected = &#91;0&#93; * len(selected_index_base)
        if return_confidence:
            return selected, &#91;0.0&#93; * len(selected)
        return selected

    fov_rad = np.deg2rad(90.0)
    fx = width / (2 * np.tan(fov_rad / 2))
    fy = height / (2 * np.tan(fov_rad / 2))
    near, far = 0.1, 30.0

    candidate_indices = torch.arange(1, current_start_frame_idx, device=device)
    r_cand = extrinsics_tensor&#91;candidate_indices, :3, :3&#93;
    t_cand = extrinsics_tensor&#91;candidate_indices, :3, 3:4&#93;
    r_cand_inv = r_cand.transpose(1, 2)
    t_cand_inv = -torch.bmm(r_cand_inv, t_cand)

    num_side = 10
    z_samples = torch.linspace(near, far, num_side, device=device)
    x_samples = torch.linspace(-1, 1, num_side, device=device)
    y_samples = torch.linspace(-1, 1, num_side, device=device)
    grid_x, grid_y, grid_z = torch.meshgrid(x_samples, y_samples, z_samples, indexing=&quot;ij&quot;)
    points_cam_base = torch.stack(&#91;
        grid_x.reshape(-1) * grid_z.reshape(-1) * (width / (2 * fx)),
        grid_y.reshape(-1) * grid_z.reshape(-1) * (height / (2 * fy)),
        grid_z.reshape(-1),
    &#93;,
                                  dim=0)

    selected_index: list&#91;int&#93; = &#91;&#93;
    selected_confidence: list&#91;float&#93; = &#91;&#93;
    for frame_idx in selected_index_base:
        base_pose = extrinsics_tensor&#91;frame_idx&#93;
        points_world = base_pose&#91;:3, :3&#93; @ points_cam_base + base_pose&#91;:3, 3:4&#93;
        points_world_batched = points_world.unsqueeze(0)
        points_in_cands = torch.bmm(r_cand_inv, points_world_batched.expand(len(candidate_indices), -1,
                                                                            -1)) + t_cand_inv

        x = points_in_cands&#91;:, 0, :&#93;
        y = points_in_cands&#91;:, 1, :&#93;
        z = points_in_cands&#91;:, 2, :&#93;
        u = (x * fx / torch.clamp(z, min=1e-6)) + width / 2
        v = (y * fy / torch.clamp(z, min=1e-6)) + height / 2

        in_view = (z &gt; near) &amp; (z &lt; far) &amp; (u &gt;= 0) &amp; (u &lt;= width) &amp; (v &gt;= 0) &amp; (v &lt;= height)
        ratios = in_view.float().mean(dim=1)
        best_idx = torch.argmax(ratios)
        selected_index.append(candidate_indices&#91;best_idx&#93;.item())
        selected_confidence.append(ratios&#91;best_idx&#93;.item())

    if return_confidence:
        return selected_index, selected_confidence
    return selected_index</code></pre></details>
<h2 id="fastvideo.models.dits.matrixgame3.utils.create_action_presets"><code>fastvideo.models.dits.matrixgame3.utils.create_action_presets</code></h2>
<pre class="doc-signature"><code>create_action_presets(num_frames: int, keyboard_dim: int = 4, seed: int = None)</code></pre>

<details><summary>Source</summary><pre><code>def create_action_presets(num_frames: int, keyboard_dim: int = 4, seed: int = None):
    if keyboard_dim not in (2, 4, 6, 7):
        raise ValueError(f&quot;keyboard_dim must be 2, 4, 6, or 7, got &#123;keyboard_dim&#125;&quot;)
    if num_frames % 4 != 1:
        raise ValueError(&quot;Matrix-Game conditioning expects num_frames to be 4k+1.&quot;)

    if seed is not None:
        random.seed(seed)

    num_samples_per_action = 4

    if keyboard_dim == 4:
        actions_single_action = &#91;&quot;forward&quot;, &quot;left&quot;, &quot;right&quot;&#93;
        actions_double_action = &#91;&quot;forward_left&quot;, &quot;forward_right&quot;&#93;
        actions_single_camera = &#91;&quot;camera_l&quot;, &quot;camera_r&quot;&#93;
        keyboard_idx = &#123;&quot;forward&quot;: 0, &quot;back&quot;: 1, &quot;left&quot;: 2, &quot;right&quot;: 3&#125;
    elif keyboard_dim == 2:
        actions_single_action = &#91;&quot;forward&quot;, &quot;back&quot;&#93;
        actions_double_action = &#91;&#93;
        actions_single_camera = &#91;&quot;camera_l&quot;, &quot;camera_r&quot;&#93;
        keyboard_idx = &#123;&quot;forward&quot;: 0, &quot;back&quot;: 1&#125;
    elif keyboard_dim == 6:
        actions_single_action = &#91;&quot;forward&quot;, &quot;back&quot;, &quot;left&quot;, &quot;right&quot;&#93;
        actions_double_action = &#91;&quot;forward_left&quot;, &quot;forward_right&quot;&#93;
        actions_single_camera = &#91;&quot;camera_l&quot;, &quot;camera_r&quot;&#93;
        keyboard_idx = &#123;&quot;forward&quot;: 0, &quot;back&quot;: 1, &quot;left&quot;: 2, &quot;right&quot;: 3, &quot;t1&quot;: 4, &quot;t2&quot;: 5&#125;
    else:  # keyboard_dim == 7
        actions_single_action = &#91;&quot;forward&quot;, &quot;back&quot;, &quot;left&quot;, &quot;right&quot;&#93;
        actions_double_action = &#91;&#93;
        actions_single_camera = &#91;&#93;
        keyboard_idx = &#123;&quot;still&quot;: 0, &quot;forward&quot;: 1, &quot;back&quot;: 2, &quot;left&quot;: 3, &quot;right&quot;: 4, &quot;a&quot;: 5, &quot;d&quot;: 6&#125;

    actions_to_test = (actions_double_action * 5 + actions_single_camera * 5 + actions_single_action * 5)
    for action in (actions_single_action + actions_double_action):
        for camera in actions_single_camera:
            actions_to_test.append(f&quot;&#123;action&#125;_&#123;camera&#125;&quot;)

    if not actions_to_test:
        actions_to_test = actions_single_action * 5

    base_action = actions_single_action + actions_single_camera
    cam_value = 0.1
    camera_value_map = &#123;
        &quot;camera_up&quot;: &#91;cam_value, 0&#93;,
        &quot;camera_down&quot;: &#91;-cam_value, 0&#93;,
        &quot;camera_l&quot;: &#91;0, -cam_value&#93;,
        &quot;camera_r&quot;: &#91;0, cam_value&#93;,
        &quot;camera_ur&quot;: &#91;cam_value, cam_value&#93;,
        &quot;camera_ul&quot;: &#91;cam_value, -cam_value&#93;,
        &quot;camera_dr&quot;: &#91;-cam_value, cam_value&#93;,
        &quot;camera_dl&quot;: &#91;-cam_value, -cam_value&#93;,
    &#125;

    data = &#91;&#93;
    for action_name in actions_to_test:
        keyboard_condition = torch.zeros((num_samples_per_action, keyboard_dim))
        mouse_condition = torch.zeros((num_samples_per_action, 2))

        for sub_act in base_action:
            if sub_act not in action_name:
                continue
            if sub_act in camera_value_map:
                mouse_condition = torch.tensor(
                    &#91;camera_value_map&#91;sub_act&#93; for _ in range(num_samples_per_action)&#93;,
                    dtype=mouse_condition.dtype,
                )
            elif sub_act in keyboard_idx:
                keyboard_condition&#91;:, keyboard_idx&#91;sub_act&#93;&#93; = 1

        data.append(&#123;
            &quot;keyboard_condition&quot;: keyboard_condition,
            &quot;mouse_condition&quot;: mouse_condition,
        &#125;)

    keyboard_condition = torch.zeros((num_frames, keyboard_dim))
    mouse_condition = torch.zeros((num_frames, 2))
    current_frame = 0
    selections = &#91;12&#93;

    while current_frame &lt; num_frames:
        rd_frame = selections&#91;random.randint(0, len(selections) - 1)&#93;
        entry = data&#91;random.randint(0, len(data) - 1)&#93;
        key_seq = entry&#91;&quot;keyboard_condition&quot;&#93;
        mouse_seq = entry&#91;&quot;mouse_condition&quot;&#93;

        if current_frame == 0:
            keyboard_condition&#91;:1&#93; = key_seq&#91;:1&#93;
            mouse_condition&#91;:1&#93; = mouse_seq&#91;:1&#93;
            current_frame = 1
        else:
            rd_frame = min(rd_frame, num_frames - current_frame)
            repeat_time = rd_frame // 4
            keyboard_condition&#91;current_frame:current_frame + rd_frame&#93; = key_seq.repeat(repeat_time, 1)
            mouse_condition&#91;current_frame:current_frame + rd_frame&#93; = mouse_seq.repeat(repeat_time, 1)
            current_frame += rd_frame

    return &#123;&quot;keyboard&quot;: keyboard_condition, &quot;mouse&quot;: mouse_condition&#125;</code></pre></details>
</div>
