GLB(https://docs.fileformat.com/3d/glb/) または GLTF(https://docs.fileformat.com/3d/gltf/) ファイルのアニメーションを評価すると、シーンをレンダリングせずに 3D オブジェクトが時間とともにどのように移動、回転、スケールするかを確認できます。この手法を使用してアニメーション データを分析したり、動きを検証したり、さらなる処理のために変換をエクスポートしたりできます。このチュートリアルでは、アニメーション化された GLB モデルをロードし、クリップを検査し、5 つのタイムスタンプを評価し、ノード変換を CSV にエクスポートします。

PythonでGLBアニメーションをロードおよび評価する

アニメーションクリップは、シーンに関連付けられたアニメーションデータを含みます。その開始時刻と終了時刻は、評価できる期間を定義します。ワークフローは、モデルをロードし、アニメーションクリップを選択し、特定の時刻で適用し、シーンノードを検査し、変換をエクスポートすることです。

Aspose.3D for Python via .NET のインストール

ここで使用されているアニメーション評価 API を提供する Aspose.3D for Python via .NET をインストールします:

pip install aspose-3d==26.10.0

詳細については、インストール ドキュメントをご覧ください。

アニメーションを評価し、ノード変換をエクスポート

次のコード例は、最初のアニメーションクリップを5つの等間隔のタイムスタンプで評価し、各ノードのローカル平行移動、回転、スケーリングを animation_transforms.csv に保存します。

import csv
import aspose.threed as a3d

INPUT_FILE = "animated_model.glb"
OUTPUT_FILE = "animation_transforms.csv"
FRAME_COUNT = 5

def get_nodes(root):
    """Recursively collect all nodes in the scene."""
    nodes = [root]

for child in root.child_nodes:
        nodes.extend(get_nodes(child))

return nodes

# Load the animated model
scene = a3d.Scene.from_file(INPUT_FILE)

# Retrieve animation clips
clips = list(scene.animation_clips)

if not clips:
    raise RuntimeError("No animation clips found.")

print(f"Found {len(clips)} animation clip(s).")

for i, item in enumerate(clips):
    print(
        f"{i}: {item.name} "
        f"({item.start:.3f} to {item.stop:.3f} seconds)"
    )

# Select the first clip and collect scene nodes
clip = clips[0]
nodes = get_nodes(scene.root_node)

print(f"\nEvaluating: {clip.name}")
print(f"Scene nodes: {len(nodes)}")

records = []

for i in range(FRAME_COUNT):
    time = float(
        clip.start +
        (clip.stop - clip.start) * i / (FRAME_COUNT - 1)
    )

# Apply animation at the requested time
    clip.apply_to(time)

print(f"\nTimestamp: {time:.3f}s")

for index, node in enumerate(nodes):
        transform = node.transform

translation = str(transform.translation)
        rotation = str(transform.rotation)
        scaling = str(transform.scaling)

records.append([
            time,
            index,
            node.name or "(unnamed)",
            translation,
            rotation,
            scaling
        ])

print(
            f"  {node.name or '(unnamed)'}: "
            f"position={translation}, "
            f"rotation={rotation}"
        )

# Write evaluated transformations to CSV
with open(
    OUTPUT_FILE, "w", newline="", encoding="utf-8"
) as file:
    writer = csv.writer(file)

writer.writerow([
        "Time",
        "Node Index",
        "Node Name",
        "Translation",
        "Rotation",
        "Scaling"
    ])

writer.writerows(records)

print(f"\nSaved animation data to {OUTPUT_FILE}")

アニメーション評価の仕組み

GLBシーンをロードしてクリップを取得する

Scene.from_file() は GLB または GLTF モデルをロードします。scene.animation_clips コレクションは利用可能なクリップを提供します。

scene = a3d.Scene.from_file("animated_model.glb")
clips = list(scene.animation_clips)

各クリップは name、start、stop を通じて名前と秒単位の時間範囲を公開します。 AnimationClip API リファレンス。

特定のタイムスタンプでアニメーションを適用する

中心的な操作は clip.apply_to(time) です。サンプルクリップは約3.708秒の長さで、5つのタイムスタンプは次のとおりです:

サンプル時間(秒)
10.000
20.927
31.854
42.781
53.708

FRAME_COUNT を変更して、サンプル数を増やすことができます。これらのサンプルは、レンダリングされた画像フレームではなく、評価されたアニメーション状態です。

変換、回転、スケーリングの読み取り

クリップを適用した後、スクリプトはすべてのシーンノードを走査し、次のように読み取ります:

  • transform.translation: ノードのローカル位置。
  • transform.rotation: ノードのローカル回転。
  • transform.scaling: ノードのローカルスケール。

これらはローカルトランスフォーメーションであり、必ずしもワールド空間座標ではありません。親ノードの変換もシーン内のノードの最終位置に影響します。アニメーションのないノードは、すべてのタイムスタンプで同じ値を保持できます。

アニメーションからのCSV出力

スクリプトは animation_transforms.csv を作成します。提供されたサンプルでは、コンソールは次のように開始します:

Found 1 animation clip(s).
0: Animation_1 (0.000 to 3.708 seconds)

Evaluating: Animation_1

CSV には、サンプリングされた各タイムスタンプごとにシーンノードごとの行が1行ずつ含まれ、次の列があります:

列説明
時間評価タイムスタンプ(秒)
ノードインデックス再帰的トラバーサルにおけるノードのインデックス
ノード名シーンノードの名前
平行移動タイムスタンプ時のローカル位置
回転タイムスタンプ時のローカル回転
スケーリングタイムスタンプ時のローカルスケール

CSVをスプレッドシートアプリケーションで開くか、Pythonで解析して、クリップ全体の変換を比較できます。

アニメーションを評価する際に確認すべきこと

複数のクリップ。 この例では clips[0] を評価します。別のアニメーションを評価するには、別のインデックスを選択するか、scene.get_animation_clip(name) を使用して名前でクリップを取得します。

サンプリング解像度。 5つのタイムスタンプは基本的な概要を提供しますが、速い動きを見逃す可能性があります。FRAME_COUNT を増やすか、特定の時間を選択して詳細を確認してください。

スケルトンとモーフターゲット。 すべてのアニメーション効果がノードのローカルな平行移動、回転、またはスケーリングの変化として現れるわけではありません。このCSVワークフローは、すべての種類のスケルトンやモーフターゲットの変形をキャプチャできません。

GLTF の依存関係。 テキストベースの .gltf ファイルは、外部バッファやテクスチャを参照することがあります。これらのファイルは、期待される相対パスに配置してください。

GLB アニメーションの評価には GPU が必要ですか?

この例では Scene.render() や Vulkan レンダリングバックエンドは呼び出されません。アニメーションプロパティを評価し、画像を生成する代わりに CSV データを書き出します。Aspose.3D のレンダリングには別途 ハードウェア要件 があり、この例の CSV のみのワークフローには適用されません。

無料の一時ライセンスを取得する

You can 無料の30日間一時ライセンスをリクエスト to evaluate Aspose.3D for Python via .NET without evaluation limitations. To apply the license in your Python application, follow the Aspose.3D ライセンス ガイド.

無料学習リソース

Aspose.3D for Python via .NET を使用して、3D モデル、アニメーション、サポートされているファイル形式の操作について詳しく学ぶには、以下のリソースをご覧ください:

結論

Aspose.3D for Python via .NET 26.10 では、AnimationClip.apply_to() を使用して、選択した時点で GLB および GLTF アニメーションクリップを評価できます。各評価後にノード変換を読み取ることで、モデルをレンダリングせずに動きを検査し、構造化されたアニメーションデータをエクスポートできます。例を適応して、追加のクリップを評価したり、サンプリング頻度を上げたり、特定のノードを解析したりしてください。

もっと読む