Kaip sukurti 3D tinklelį su Aspose.3D Python programoje

Kaip sukurti 3D tinklelį su Aspose.3D Python programoje

Aspose.3D FOSS for Python leidžia kurti 3D geometriją visiškai kode: nereikia išorinio modeliavimo įrankio. Jūs sukuriate a Mesh, užpildykite ją viršūnių pozicijomis (control_points) ir veidų apibrėžimus (polygons), pridėkite pasirenkamus viršūnių atributus, pvz., normalės, tada įrašykite sceną į bet kurį palaikomą formatą.

Žingsnis po žingsnio vadovas

Žingsnis 1: Įdiekite paketą

Įdiekite Aspose.3D FOSS iš PyPI. Nereikia jokių natūralių plėtinių ar kompiliatoriaus įrankių grandinės.

pip install aspose-3d-foss

Patikrinkite įdiegimą:

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

Palaikomos Python versijos: 3.7, 3.8, 3.9, 3.10, 3.11, 3.12.


Žingsnis 2: Sukurkite sceną ir mazgą

Kiekvienas tinklas turi gyventi scenos grafike. Sukurkite a Scene ir pridėkite pavadintą Node elementą, skirtą laikyti tinklą:

from aspose.threed import Scene

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

Mazgo pavadinimas išsaugomas eksportuojamame faile ir yra naudingas derinimui bei vėlesniam gavimui per node.get_child("triangle").


Žingsnis 3: Sukurkite Mesh objektą

Sukurkite egzempliorių Mesh su pasirenkamu aprašomu pavadinimu:

from aspose.threed.entities import Mesh

mesh = Mesh("triangle")

Tinklas iš pradžių yra tuščias: nėra viršūnių, nėra daugiakampių. Jūs jį užpildysite tolesniais žingsniais.


Žingsnis 4: Pridėkite kontrolinius taškus (viršūnes)

Kontroliniai taškai yra viršūnių pozicijos. Kiekviena viršūnė saugoma kaip Vector4(x, y, z, w) kur w=1 nurodo tašką 3D erdvėje:

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

Svarbu: mesh.control_points grąžina kopiją iš vidinio viršūnių sąrašo (gautojas vykdo list(self._control_points)) mesh.control_points.append(v) prideda prie kopijos, o ne prie tinklelio, todėl viršūnė tyliai išmetama. Visada naudokite mesh._control_points.append(v) pridėti viršūnes. Prieiga prie privačios būsenos per _control_points yra žinomas apeinimas; sąsaja gali pasikeisti būsimoje bibliotekos versijoje.


Žingsnis 5: Sukurkite daugiakampių veidus

Apibrėžkite veido topologiją naudodami viršūnių indeksus. Perduokite viršūnių indeksus į create_polygon(). Trys indeksai sukuria trikampį; keturi – keturkampį:

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

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

Keturkampio tinkleliui turėtumėte perduoti keturis indeksus: mesh.create_polygon(0, 1, 2, 3).

Indeksai turi būti galiojančios pozicijos control_points (0‑indeksų, ribose). Vėjimo tvarka yra prieš laikrodžio rodyklę išorės nukreiptų normalių atveju.


Žingsnis 6: Pridėti viršūnių normas

Viršūnių normalių saugoma kaip VertexElement prijungta prie tinklelio. Naudokite mesh.create_element() su VertexElementType.NORMAL, MappingMode.CONTROL_POINT, ir 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 reiškia po vieną normalią viršūnei. ReferenceMode.DIRECT reiškia, kad normalų duomenys skaitomi tokia pačia tvarka kaip valdymo taškai (nėra papildomo indeksų buferio).

Normaliniai vektoriai naudoja FVector4(x, y, z, w) su w=0 nurodyti kryptį, o ne poziciją. FVector4 yra viengubo tikslumo slankaus kablelio vektorius; viršūnės atributo duomenys VertexElementFVector pakaitinės klasės naudoja šį tipą.


Žingsnis 7: Prijungti tinklą (Mesh) prie mazgo (Node) ir išsaugoti

Pridėkite tinklą prie mazgo, tada išsaugokite sceną:

node.add_entity(mesh)

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

Visas veikiantis scenarijus (visi žingsniai sujungti):

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

Dažnos problemos

ProblemaSprendimas
IndexError į create_polygonPatikrinkite, ar visi indeksai yra range(len(mesh.control_points)). Indeksai yra nulio pagrindu.
Mesh eksportas be viršūniųmesh.control_points.append(...) tyliai pašalina viršūnes, nes savybė grąžina kopiją. Naudokite mesh._control_points.append(...) vietoj to.
Normalų skaičius neatitinka viršūnių skaičiausNaudojant MappingMode.CONTROL_POINT + ReferenceMode.DIRECT, normals.data turi turėti lygiai len(control_points) įrašus.
Mesh trūksta iš įrašyto failoPatvirtinkite, kad node.add_entity(mesh) buvo iškviesta prieš scene.save(). Tinklas, neprijungtas prie jokio mazgo, nėra eksportuojamas.
Neteisinga vingio tvarka (veidas atrodo nematomas)Prieš laikrodžio rodyklę esanti viršūnių tvarka sukuria išorės nukreiptą normalę. Apverskite indeksų tvarką create_polygon apversti tai.
polygon_count grąžina 0polygon_count skaito tą patį sąrašą kaip polygons. Jei create_polygon nebuvo iškviesta, sąrašas yra tuščias.
Normalės atrodo neteisingos peržiūros programojeUžtikrinkite, kad visi normalės vektoriai būtų vienetinio ilgio. Apskaičiuokite su n / abs(n) arba perduokite iš anksto normalizuotas reikšmes.

Dažnai užduodami klausimai

Kuo skiriasi Vector3 ir Vector4 valdymo taškams?

control_points saugo Vector4 objektus. w komponentas yra homogeninė koordinatė: naudokite w=1 viršūnių pozicijoms ir w=0 krypties vektoriams, pvz., normalėms. Vector3 naudojamas transformacijoms (perkėlimui, mastui), bet ne geometrijos saugojimui.

Ar galiu sukurti tinklą su keturkampiais vietoj trikampių?

Taip. Iškviesti mesh.create_polygon(0, 1, 2, 3) su keturiais indeksais, kad apibrėžtumėte kvadratą. Kai kurie išsaugojimo formatai (STL, 3MF) reikalauja trikampių ir automatiškai kvadratus paverčia į trikampius. glTF ir COLLADA išsaugo kvadratus.

Kaip pridėti UV koordinates?

Naudokite mesh.create_element_uv(TextureMapping.DIFFUSE, MappingMode.POLYGON_VERTEX) sukurti VertexElementUV difuziniam kanalui, tada užpildyti jo data sąrašą su Vector4 įrašus. UV koordinatės naudoja x ir y; z ir w paprastai yra 0. Pirmasis argumentas turi būti TextureMapping konstanta (pvz., TextureMapping.DIFFUSE) nurodanti, kuriam tekstūros lizdui priklauso UV sluoksnis.

Ar tinklui reikia normalių, kad būtų teisingai eksportuotas?

Ne. Normals yra neprivalomi. Jei jie praleidžiami, dauguma peržiūros programų apskaičiuoja per-face normals pagal daugiakampio vingio tvarką. Išreikštų per-vertex normals pridėjimas sukuria lygesnį apšvietimą.

Ar galiu pridėti kelis tinklus į vieną mazgą?

Taip. Iškvieskite node.add_entity(mesh) kelis kartus. Kiekvienas iškvietimas prideda naują objektą prie node.entities. Kai kurie formatai gali suplokštinti kelis objektus į vieną eksportuojant.

Kaip sutrianguliuoti tinklą, kuriame yra mišrių daugiakampių tipų?

Iškvieskite mesh.triangulate() konvertuoti visus kvadratus ir N-gonus į trikampius vietoje. Tai naudinga prieš išsaugant į formatus, kurie palaiko tik trikampius.

 Lietuvių