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.NORMAL、MappingMode.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")一般的な問題
| Issue | Resolution |
|---|---|
IndexError in create_polygon | すべてのインデックスが range(len(mesh.control_points)) の範囲内にあることを確認してください。インデックスは 0 ベースです。 |
| Mesh exports with zero vertices | mesh.control_points.append(...) はプロパティがコピーを返すため、頂点を黙って破棄します。代わりに mesh._control_points.append(...) を使用してください。 |
| Normals count does not match vertex count | MappingMode.CONTROL_POINT と ReferenceMode.DIRECT を使用する場合、normals.data は正確に len(control_points) 個のエントリを持つ必要があります。 |
| Mesh missing from saved file | node.add_entity(mesh) が scene.save() の前に呼び出されたことを確認してください。ノードに添付されていないメッシュはエクスポートされません。 |
| Wrong winding order (face appears invisible) | 反時計回りの頂点順序は外向きの法線を生成します。create_polygon のインデックス順序を逆にして反転させてください。 |
polygon_count returns 0 | polygon_count は polygons と同じリストを読み取ります。create_polygon が呼び出されていない場合、リストは空です。 |
| Normals appear incorrect in viewer | すべての法線ベクトルが単位長さであることを確認してください。n / abs(n) で計算するか、正規化済みの値を渡してください。 |
よくある質問
制御点における Vector3 と Vector4 の違いは何ですか?
control_points は Vector4 オブジェクトを格納します。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 座標は x と y を使用します;z と w は通常 0 です。最初の引数は、UV レイヤーが属するテクスチャ スロットを識別する TextureMapping 定数(例: TextureMapping.DIFFUSE)でなければなりません。
メッシュは正しくエクスポートするために法線が必要ですか?
いいえ。法線はオプションです。省略した場合、ほとんどのビューアはポリゴンの winding 順序から面ごとの法線を計算します。明示的な頂点ごとの法線を追加すると、シェーディングがより滑らかになります。
1つのノードに複数のメッシュを追加できますか?
はい。node.add_entity(mesh) を複数回呼び出します。各呼び出しは node.entities に新しいエンティティを追加します。エクスポート時に、いくつかのフォーマットでは複数のエンティティが1つにフラット化されることがあります。
混合ポリゴンタイプのメッシュをどのように三角形分割しますか?
mesh.triangulate() を呼び出して、すべてのクアッドと N‑ゴンをその場で三角形に変換します。これは、三角形のみをサポートする形式に保存する前に便利です。