Как да създадете 3D мрежа с Aspose.3D в Python

Как да създадете 3D мрежа с Aspose.3D в Python

Aspose.3D FOSS for Python ви позволява да създавате 3D геометрия изцяло чрез код: не е необходим външен инструмент за моделиране. Създавате Mesh, попълвате го с позиции на върхове (control_points) и дефиниции на лица (polygons), прикрепвате атрибути на върховете по избор, като нормали, след което запазвате сцената във всеки поддържан формат.

Ръководство стъпка по стъпка

Стъпка 1: Инсталирайте пакета

Инсталирайте Aspose.3D FOSS от PyPI. Не са необходими нативни разширения или компилаторски инструментариум.

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 Object

Създайте екземпляр на Mesh с незадължително описателно име:

from aspose.threed.entities import Mesh

mesh = Mesh("triangle")

Мрежата е първоначално празна: няма върхове, няма полигони. Попълвате я в следните стъпки.


Стъпка 4: Добавяне на контролни точки (върхове)

Контролните точки са позициите на върховете. Всеки връх се съхранява като Vector4(x, y, z, w), където w=1 указва точка в 3D пространство:

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)}")

Важно: mesh.control_points връща копие на вътрешния списък с върхове (гетърът изпълнява list(self._control_points)). Извикването на mesh.control_points.append(v) добавя към копието, а не към мрежата, така че върхът се отхвърля без известие. Винаги използвайте mesh._control_points.append(v) за добавяне на върхове. Достъпът до частното състояние чрез _control_points е известен обходен метод; интерфейсът може да се промени в бъдеща версия на библиотеката.


Стъпка 5: Създаване на полигонни лица

Определете топологията на лицето, използвайки индекси на върхове. Предайте индексите на върховете на create_polygon(). Три индекса създават триъгълник; четири създават четириъгълник:

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

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

За quad mesh трябва да предадете четири индекса: 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 означава един нормал за връх. ReferenceMode.DIRECT означава, че данните за нормалите се четат в същия ред като контролните точки (без допълнителен индексен буфер).

Нормалните вектори използват FVector4(x, y, z, w) с w=0, за да посочат посока, а не позиция. FVector4 е вектор с плаваща запетая с единична точност; данните за атрибутите на върховете в подкласовете на VertexElementFVector използват този тип.


Стъпка 7: Прикрепете Mesh към Node и запазете

Добавете мрежата към възела, след това запазете сцената:

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 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 0polygon_count чете същия списък като polygons. Ако create_polygon не е извикано, списъкът е празен.
Normals appear incorrect in viewerУверете се, че всички нормални вектори са с дължина 1. Изчислете ги с n / abs(n) или подайте предварително нормализирани стойности.

Често задавани въпроси

Каква е разликата между Vector3 и Vector4 за контролните точки?

control_points съхранява Vector4 обекти. Компонентът w е хомогенната координата: използвайте w=1 за позиции на върховете и w=0 за векторите на посока, като нормали. Vector3 се използва за трансформации (превод, мащаб), но не за съхранение на геометрия.

Мога ли да построя мрежа с четириъгълници вместо триъгълници?

Да. Извикайте mesh.create_polygon(0, 1, 2, 3) с четири индекса, за да дефинирате четириъгълник. Някои цели за запазване (STL, 3MF) изискват триъгълници и автоматично ще триангулират четириъгълници. glTF и COLLADA запазват четириъгълници.

Как да добавя UV координати?

Използвайте mesh.create_element_uv(TextureMapping.DIFFUSE, MappingMode.POLYGON_VERTEX), за да създадете VertexElementUV за дифузния канал, след което попълнете неговия списък data с Vector4 елементи. UV координатите използват x и y; z и w обикновено са 0. Първият аргумент трябва да бъде константа TextureMapping (например TextureMapping.DIFFUSE), определяща към кой слот за текстура принадлежи UV слой.

Трябва ли мрежата да има нормали, за да се експортира правилно?

Не. Нормалите са незадължителни. Ако се пропуснат, повечето визуализатори изчисляват нормали за лице от реда на въртене на полигоните. Добавянето на явни нормали за върхове осигурява по‑гладко осветление.

Мога ли да добавя няколко мрежи към един възел?

Да. Извикайте node.add_entity(mesh) многократно. Всяко извикване добавя нова единица към node.entities. Някои формати могат да обединят множество единици в една при експортиране.

Как да триангулирам мрежа със смесени типове полигони?

Извикайте mesh.triangulate(), за да конвертирате всички четириъгълници и N‑гонове в триъгълници на място. Това е полезно преди запазване във формати, които поддържат само триъгълници.

 Български