Pythonで3Dモデルをロードする方法

Pythonで3Dモデルをロードする方法

Aspose.3D FOSS for Python は、ネイティブ依存なしで 3D ファイルを開くためのシンプルな API を提供します。ファイルを Scene オブジェクトにロードした後、ノード階層をたどり、シーン内のすべてのメッシュの生ジオメトリデータを読み取ることができます。.

ステップバイステップ ガイド

ステップ 1: パッケージをインストールする

PyPI から Aspose.3D FOSS をインストールします。追加のシステムライブラリは必要ありません。.

pip install aspose-3d-foss

サポートされている Python バージョン: 3.7, 3.8, 3.9, 3.10, 3.11, 3.12.


ステップ 2: Scene クラスをインポートする

この Scene クラスはすべての 3D データのトップレベルコンテナです。必要なロードオプションクラスとともにインポートしてください。.

from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptions

すべての公開クラスは以下の下にあります aspose.threed またはそのサブパッケージ(aspose.threed.entities, aspose.threed.formats, aspose.threed.utilities).


ステップ 3: ファイルをロードする

静的メソッドを使用してください Scene.from_file() 任意のサポートされている形式を開くメソッドです。ライブラリはファイル拡張子から形式を自動的に検出します。.

##Automatic format detection
scene = Scene.from_file("model.obj")

代わりに、 Scene インスタンスを作成し、呼び出します open();;ロードオプションを渡したり、エラーを明示的に処理したい場合に便利です::

scene = Scene()
scene.open("model.obj")

両方の方法は OBJ、STL(バイナリおよび ASCII)、glTF 2.0 / GLB、COLLADA(DAE)、および 3MF ファイルをサポートしています。.


ステップ 4: Scene ノードを走査する

ロードされたシーンはツリーです Node オブジェクトがルートになる scene.root_node.。再帰的にイテレートしてすべてのノードを見つけます:

from aspose.threed import Scene, Node

scene = Scene.from_file("model.obj")

def walk(node: Node, depth: int = 0) -> None:
    indent = "  " * depth
    print(f"{indent}Node: {node.name!r}")
    for child in node.child_nodes:
        walk(child, depth + 1)

walk(scene.root_node)

Node は0個以上の Entity オブジェクト(メッシュ、カメラ、ライト)。チェック node.entities 何がアタッチされているか確認します。.


ステップ 5: 頂点およびポリゴンデータにアクセスする

ノードのエンティティをキャストして Mesh そしてその制御点(頂点位置)とポリゴン(面インデックスリスト)を読み取ります:

from aspose.threed import Scene
from aspose.threed.entities import Mesh

scene = Scene.from_file("model.obj")

for node in scene.root_node.child_nodes:
    for entity in node.entities:
        if isinstance(entity, Mesh):
            mesh: Mesh = entity
            print(f"Mesh '{node.name}': "
                  f"{len(mesh.control_points)} vertices, "
                  f"{len(mesh.polygons)} polygons")

            # First vertex position
            if mesh.control_points:
                v = mesh.control_points[0]
                print(f"  First vertex: ({v.x:.4f}, {v.y:.4f}, {v.z:.4f})")

            # First polygon face (list of control-point indices)
            if mesh.polygons:
                print(f"  First polygon: {mesh.polygons[0]}")

mesh.control_points はリストです Vector4 オブジェクト; x, y, z 位置を保持し、 w は同次座標です(通常は 1.0)。.

mesh.polygons は整数のリストのリストで、各内部リストは 1 つの面に対する制御点インデックスの順序付けられた集合です。.


ステップ 6: フォーマット固有のロードオプションを適用する

OBJ ファイルの解釈方法を細かく制御するには、 ObjLoadOptions インスタンスを scene.open():

from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptions

options = ObjLoadOptions()
options.flip_coordinate_system = True   # Convert right-hand Y-up to Z-up
options.scale = 0.01                    # Convert centimetres to metres
options.enable_materials = True         # Load .mtl material file
options.normalize_normal = True         # Normalize all normals to unit length

scene = Scene()
scene.open("model.obj", options)

STL ファイルの場合、同等のクラスは StlLoadOptions.。glTF では、 GltfLoadOptions.。以下をご覧ください API リファレンス 完全な一覧については。.


一般的な問題と対策

呼び出し時の FileNotFoundError Scene.from_file()

パスは絶対パスであるか、実行時の作業ディレクトリに対して正しい相対パスでなければなりません。使用してください pathlib.Path 信頼できるパスを構築するには:

from pathlib import Path
from aspose.threed import Scene

path = Path(__file__).parent / "assets" / "model.obj"
scene = Scene.from_file(str(path))

mesh.polygons STL ファイルの読み込み後、空です

STL ファイルは三角形をインデックス化されたメッシュではなく、生のファセットとして格納します。読み込み後、ポリゴンはそれらのファセットから合成されます。もし polygons が空のように見える場合、次を確認してください len(mesh.control_points);;カウントが 3 の倍数である場合、ジオメトリはインデックスなし形式で格納されており、連続する 3 つの頂点が 1 つの三角形を構成します。.

座標系の不一致(モデルが回転または鏡像になっている)

ツールによって異なる座標系(Y-up と Z-up、左手系 と 右手系)を使用します。設定してください ObjLoadOptions.flip_coordinate_system = True または、ルートノードの回転を適用してください Transform 読み込み後に.

AttributeError: 'NoneType' object has no attribute 'polygons'

ノードのエンティティリストには、メッシュ以外のエンティティ(カメラ、ライト)が含まれる場合があります。常に次でガードしてください isinstance(entity, Mesh) キャストする前に.


よくある質問 (FAQ)

どの 3D フォーマットを読み込めますか??

OBJ (Wavefront)、STL(バイナリおよび ASCII)、glTF 2.0 / GLB、COLLADA (DAE)、および 3MF。FBX のトークン化は部分的にサポートされていますが、完全なパースはまだ完了していません。.

OBJ ファイルを読み込むと、the も読み込まれますか .mtl material?

はい、when ObjLoadOptions.enable_materials = True (the default)。ライブラリは the を探します .mtl file を同じディレクトリの the に .obj file。If the .mtl is missing、ジオメトリは引き続きロードされ、警告が出力されます。.

パスではなくバイトストリームからファイルを読み込むことはできますか??

はい。. scene.open() 任意の file-like object を受け入れ、with a .read() method を、file path 文字列に加えて受け付けます。開いたバイナリストリームを渡します(例:., io.BytesIO) 直接に。. Scene.from_file() ファイルパス文字列のみを受け付けます。.

表面法線はどうやって取得しますか??

ロード後にチェック mesh.get_element(VertexElementType.NORMAL). これは返す VertexElementNormal その data リストには参照ごとに1つの法線ベクトルが含まれ、次に従ってマッピングされます mapping_mode および reference_mode.

from aspose.threed.entities import Mesh, VertexElementType

normals = mesh.get_element(VertexElementType.NORMAL)
if normals:
    print(normals.data[0])  # First normal vector

このライブラリは、複数のファイルを同時にロードする際にスレッドセーフですか??

Scene オブジェクトは独立しています。別々のファイルを別々の Scene インスタンスを別スレッドから作成することは、単一の Scene 外部ロックなしでスレッド間で。.

 日本語