PythonでAspose.3Dを使用して3Dメッシュを構築する方法

PythonでAspose.3Dを使用して3Dメッシュを構築する方法

Aspose.3D FOSS for Python は、外部のモデリングツールを必要とせず、コードだけで 3D ジオメトリを構築できます。Mesh を作成し、頂点位置(control_points)と面定義(polygons)でそれを埋め、法線などのオプションの頂点属性を付加し、シーンを任意のサポートされている形式で保存します。

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

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

PyPI から Aspose.3D FOSS をインストールします。ネイティブ拡張やコンパイラ ツールチェーンは必要ありません。

pip install aspose-3d-foss

インストールを確認する:

from aspose.threed import Scene
print("Aspose.3D FOSS ready")

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


ステップ 2: シーンとノードを作成する

すべてのメッシュはシーン グラフ内に存在しなければなりません。Scene を作成し、メッシュを保持するために名前付き Node を追加します:

from aspose.threed import Scene

scene = Scene()
node = scene.root_node.create_child_node("triangle")

ノード名はエクスポートされたファイルに保持され、デバッグや後の取得に node.get_child("triangle") を介して役立ちます。


ステップ 3: メッシュ オブジェクトを作成

オプションの説明名を付けて Mesh をインスタンス化します:

from aspose.threed.entities import Mesh

mesh = Mesh("triangle")

メッシュは最初は空です:頂点がなく、ポリゴンもありません。以下の手順でそれを構築します。


ステップ 4: 制御点(頂点)を追加

制御点は頂点の位置です。各頂点は Vector4(x, y, z, w) として保存され、w=1 は3次元空間の点を示します:

from aspose.threed.utilities import Vector4

##Vertex 0: origin
# Note: control_points returns a copy of the internal vertex list.
# Appending to the returned copy discards the vertex silently.
# Use _control_points to mutate the backing list directly.
# This is a known library limitation — a public add_control_point() API is not yet available.
mesh._control_points.append(Vector4(0.0, 0.0, 0.0, 1.0))

##Vertex 1: 1 unit along X
mesh._control_points.append(Vector4(1.0, 0.0, 0.0, 1.0))

##Vertex 2: apex
mesh._control_points.append(Vector4(0.5, 1.0, 0.0, 1.0))

print(f"Vertices added: {len(mesh.control_points)}")

Important: mesh.control_points は内部頂点リストの コピー を返します(getter は list(self._control_points) を実行します)。mesh.control_points.append(v) を呼び出すとコピーに追加され、メッシュには追加されないため、頂点は黙って破棄されます。常に mesh._control_points.append(v) を使用して頂点を追加してください。_control_points を介したプライベート状態へのアクセスは既知の回避策です;インターフェイスは将来のバージョンで変更される可能性があります。


Step 5: ポリゴン面の作成

頂点インデックスを使用して面のトポロジーを定義します。頂点インデックスをcreate_polygon()に渡します。3つのインデックスで三角形が生成され、4つで四角形が生成されます:

##Triangle: connect vertices 0 → 1 → 2
mesh.create_polygon(0, 1, 2)

print(f"Polygon count: {mesh.polygon_count}")

クアッドメッシュの場合、4つのインデックスを渡します: mesh.create_polygon(0, 1, 2, 3)

インデックスは control_points 内の有効な位置である必要があります(0 ベースで、範囲内)。外向き法線の場合、ワインディング順序は反時計回りです。


ステップ 6: 頂点法線を追加

頂点法線は、メッシュに添付された VertexElement として保存されます。mesh.create_element()VertexElementType.NORMALMappingMode.CONTROL_POINT、および ReferenceMode.DIRECT と共に使用してください:

from aspose.threed.entities import VertexElementType, MappingMode, ReferenceMode, VertexElementNormal
from aspose.threed.utilities import Vector4, FVector4

##Create the normal element (returns VertexElementNormal, a VertexElementFVector subclass)
normals: VertexElementNormal = mesh.create_element(
    VertexElementType.NORMAL,
    MappingMode.CONTROL_POINT,
    ReferenceMode.DIRECT
)

##One normal per vertex: all pointing out of the XY plane (0, 0, 1)
normals.set_data([
    FVector4(0, 0, 1, 0),   # vertex 0
    FVector4(0, 0, 1, 0),   # vertex 1
    FVector4(0, 0, 1, 0),   # vertex 2
])

print("Normal layer attached.")

MappingMode.CONTROL_POINT は、頂点ごとに1つの法線を意味します。
ReferenceMode.DIRECT は、法線データが制御点と同じ順序で読み取られることを意味します(余分なインデックスバッファはありません)。

法線ベクトルは FVector4(x, y, z, w)w=0 を使用して、位置ではなく方向を示します。 FVector4 は単精度浮動小数点ベクトルです; VertexElementFVector のサブクラスにある頂点属性データはこの型を使用します。


ステップ 7: メッシュをノードにアタッチして保存

メッシュをノードに追加し、シーンを保存します:

node.add_entity(mesh)

scene.save("triangle.gltf")
print("Saved triangle.gltf")

すべての手順を組み合わせた完全に動作するスクリプト:

from aspose.threed import Scene
from aspose.threed.entities import Mesh, VertexElementType, MappingMode, ReferenceMode, VertexElementNormal
from aspose.threed.utilities import Vector3, Vector4, FVector4

scene = Scene()
node = scene.root_node.create_child_node("triangle")

mesh = Mesh("triangle")

##Add 3 vertices (x, y, z, w)
# Use _control_points to mutate the backing list directly (control_points returns a copy)
mesh._control_points.append(Vector4(0.0, 0.0, 0.0, 1.0))
mesh._control_points.append(Vector4(1.0, 0.0, 0.0, 1.0))
mesh._control_points.append(Vector4(0.5, 1.0, 0.0, 1.0))

##Create a triangle polygon
mesh.create_polygon(0, 1, 2)

##Add normals (create_element returns VertexElementNormal, a VertexElementFVector subclass)
normals: VertexElementNormal = mesh.create_element(VertexElementType.NORMAL, MappingMode.CONTROL_POINT, ReferenceMode.DIRECT)
normals.set_data([
    FVector4(0, 0, 1, 0),
    FVector4(0, 0, 1, 0),
    FVector4(0, 0, 1, 0),
])

node.add_entity(mesh)
scene.save("triangle.gltf")

一般的な問題

IssueResolution
IndexError in create_polygonすべてのインデックスが range(len(mesh.control_points)) の範囲内にあることを確認してください。インデックスは 0 ベースです。
Mesh exports with zero verticesmesh.control_points.append(...) はプロパティがコピーを返すため、頂点を黙って破棄します。代わりに mesh._control_points.append(...) を使用してください。
Normals count does not match vertex countMappingMode.CONTROL_POINTReferenceMode.DIRECT を使用する場合、normals.data は正確に len(control_points) 個のエントリを持つ必要があります。
Mesh missing from saved filenode.add_entity(mesh)scene.save() の前に呼び出されたことを確認してください。ノードに添付されていないメッシュはエクスポートされません。
Wrong winding order (face appears invisible)反時計回りの頂点順序は外向きの法線を生成します。create_polygon のインデックス順序を逆にして反転させてください。
polygon_count returns 0polygon_countpolygons と同じリストを読み取ります。create_polygon が呼び出されていない場合、リストは空です。
Normals appear incorrect in viewerすべての法線ベクトルが単位長さであることを確認してください。n / abs(n) で計算するか、正規化済みの値を渡してください。

よくある質問

制御点における Vector3Vector4 の違いは何ですか?

control_pointsVector4 オブジェクトを格納します。w コンポーネントは同次座標です:w=1 を頂点位置に、w=0 を法線などの方向ベクトルに使用します。Vector3 は変換(平行移動、スケール)に使用されますが、ジオメトリの格納には使用されません。

三角形の代わりに四角形でメッシュを作成できますか?

はい。mesh.create_polygon(0, 1, 2, 3) を4つのインデックスで呼び出してクアッドを定義します。一部の保存先(STL、3MF)は三角形を必要とし、クアッドを自動的に三角形化します。glTF と COLLADA はクアッドを保持します。

UV座標はどうやって追加しますか?

mesh.create_element_uv(TextureMapping.DIFFUSE, MappingMode.POLYGON_VERTEX) を使用してディフューズ チャネル用の VertexElementUV を作成し、次にその data リストに Vector4 エントリを追加します。UV 座標は xy を使用します;zw は通常 0 です。最初の引数は、UV レイヤーが属するテクスチャ スロットを識別する TextureMapping 定数(例: TextureMapping.DIFFUSE)でなければなりません。

メッシュは正しくエクスポートするために法線が必要ですか?

いいえ。法線はオプションです。省略した場合、ほとんどのビューアはポリゴンの winding 順序から面ごとの法線を計算します。明示的な頂点ごとの法線を追加すると、シェーディングがより滑らかになります。

1つのノードに複数のメッシュを追加できますか?

はい。node.add_entity(mesh) を複数回呼び出します。各呼び出しは node.entities に新しいエンティティを追加します。エクスポート時に、いくつかのフォーマットでは複数のエンティティが1つにフラット化されることがあります。

混合ポリゴンタイプのメッシュをどのように三角形分割しますか?

mesh.triangulate() を呼び出して、すべてのクアッドと N‑ゴンをその場で三角形に変換します。これは、三角形のみをサポートする形式に保存する前に便利です。

 日本語