Funktioner och funktionaliteter
Aspose.3D FOSS för Python tillhandahåller ett komplett scene‑graph‑API för att läsa, konstruera och skriva 3D‑innehåll i flera branschstandardformat. Denna sida dokumenterar varje huvudfunktionsområde med fungerande Python-kodexempel som använder det faktiska bibliotekets API.
Installation och konfiguration
Installera biblioteket från PyPI med ett enda kommando:
pip install aspose-3d-fossInga ytterligare systempaket, inhemska tillägg eller kompilatorverktygskedjor krävs. Biblioteket är rent Python och stöder Python 3.7 till 3.12 på Windows, macOS och Linux.
För att verifiera installationen:
from aspose.threed import Scene
scene = Scene()
print("Aspose.3D FOSS installed successfully")
print(f"Root node name: {scene.root_node.name}")Funktioner och funktionaliteter
Formatstöd
Aspose.3D FOSS för Python läser och skriver följande format:
| Format | Filändelse | Läs | Skriv | Anteckningar |
|---|---|---|---|---|
| Wavefront OBJ | .obj | Ja | Ja | .mtl-materialladdning stöds |
| STL (binär) | .stl | Ja | Ja | Rundresa verifierad (39 tester) |
| STL (ASCII) | .stl | Ja | Ja | Rundresa verifierad |
| glTF 2.0 | .gltf | Ja | Ja | Fullständig scengraf bevarad |
| GLB (binär glTF) | .glb | Ja | Ja | Enfilig binärbehållare |
| COLLADA | .dae | Ja | Ja | Scenhierarki och material |
| 3MF | .3mf | Ja | Ja | Additivt tillverkningsformat |
| FBX | .fbx | Delvis | Nej | Tokenizer fungerar; parser har kända buggar |
Laddning av OBJ med alternativ
ObjLoadOptions styr hur OBJ-filer tolkas:
from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptions
options = ObjLoadOptions()
options.enable_materials = True # Load accompanying .mtl file
options.flip_coordinate_system = False # Preserve original handedness
options.normalize_normal = True # Normalize vertex normals to unit length
options.scale = 1.0 # Apply a uniform scale factor at load time
scene = Scene()
scene.open("model.obj", options)
print(f"Loaded {len(scene.root_node.child_nodes)} top-level nodes")Spara till STL
StlSaveOptions styr binär vs. ASCII-utdata och andra STL-specifika inställningar:
from aspose.threed import Scene
from aspose.threed.formats import StlSaveOptions
scene = Scene.from_file("model.obj")
options = StlSaveOptions()
scene.save("output.stl", options)Scengraf
Allt 3D-innehåll är organiserat som ett träd av Node objekt. Roten av trädet är scene.root_node. Varje nod kan innehålla barnnoder och bära en Entity (mesh, kamera eller ljus) plus en Transform.
Traversera scenhierarkin
from aspose.threed import Scene
scene = Scene.from_file("model.glb")
def traverse(node, depth=0):
indent = " " * depth
entity_type = type(node.entity).__name__ if node.entity else "none"
print(f"{indent}{node.name} [{entity_type}]")
for child in node.child_nodes:
traverse(child, depth + 1)
traverse(scene.root_node)Bygga en scen programatiskt
from aspose.threed import Scene, Node, Entity
from aspose.threed.entities import Mesh
from aspose.threed.utilities import Vector3
scene = Scene()
root = scene.root_node
##Create a child node and position it
child = root.create_child_node("my_object")
child.transform.translation = Vector3(1.0, 0.0, 0.0)
child.transform.scaling = Vector3(2.0, 2.0, 2.0)
scene.save("constructed.glb")Inspektera GlobalTransform
GlobalTransform ger nodens världsrumstransform efter att ha ackumulerat alla förfäders transformationer:
from aspose.threed import Scene
scene = Scene.from_file("model.dae")
for node in scene.root_node.child_nodes:
gt = node.global_transform
print(f"Node: {node.name}")
print(f" World translation: {gt.translation}")
print(f" World scale: {gt.scale}")Mesh API
Den Mesh entiteten ger åtkomst till geometridata inklusive kontrollpunkter (vertices), polygoner och vertexelement för normaler, UV:er och färger.
Läsa Mesh-geometri
from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptions
options = ObjLoadOptions()
options.enable_materials = True
options.flip_coordinate_system = False
scene = Scene()
scene.open("model.obj", options)
for node in scene.root_node.child_nodes:
if node.entity is None:
continue
mesh = node.entity
print(f"Mesh: {node.name}")
print(f" Vertices: {len(mesh.control_points)}")
print(f" Polygons: {len(mesh.polygons)}")Åtkomst till vertexelement
Vertexelement innehåller data per vertex eller per polygon. De vanligaste elementen är normaler, UV-koordinater, vertexfärger och mjukgöringsgrupper:
from aspose.threed import Scene
from aspose.threed.entities import VertexElementNormal, VertexElementUV
scene = Scene.from_file("model.obj")
for node in scene.root_node.child_nodes:
if node.entity is None:
continue
mesh = node.entity
# Iterate vertex elements to find normals and UVs
for element in mesh.vertex_elements:
if isinstance(element, VertexElementNormal):
print(f" Normals count: {len(element.data)}")
elif isinstance(element, VertexElementUV):
print(f" UV count: {len(element.data)}")Materialsystem
Aspose.3D FOSS stöder två materialtyper: LambertMaterial (diffus skuggning) och PhongMaterial (speculär skuggning). Båda laddas automatiskt från .mtl-filer när man använder ObjLoadOptions med enable_materials = True.
Läsa material från OBJ
from aspose.threed import Scene
from aspose.threed.shading import LambertMaterial, PhongMaterial
from aspose.threed.formats import ObjLoadOptions
options = ObjLoadOptions()
options.enable_materials = True
scene = Scene()
scene.open("model.obj", options)
for node in scene.root_node.child_nodes:
mat = node.material
if mat is None:
continue
print(f"Node: {node.name}")
if isinstance(mat, PhongMaterial):
print(f" Type: Phong")
print(f" Diffuse: {mat.diffuse_color}")
print(f" Specular: {mat.specular_color}")
elif isinstance(mat, LambertMaterial):
print(f" Type: Lambert")
print(f" Diffuse: {mat.diffuse_color}")Tilldela ett material programatiskt
from aspose.threed import Scene, Node
from aspose.threed.shading import PhongMaterial
from aspose.threed.utilities import Vector3
scene = Scene.from_file("model.glb")
material = PhongMaterial()
material.diffuse_color = Vector3(0.8, 0.2, 0.2) # Red diffuse
material.specular_color = Vector3(1.0, 1.0, 1.0) # White specular
##Apply to the first mesh node
for node in scene.root_node.child_nodes:
if node.entity is not None:
node.material = material
break
scene.save("recolored.glb")Matematikverktyg
Den aspose.threed.utilities modulen tillhandahåller alla geometriska matematiska typer som behövs för scenkonstruktion och inspektion.
| Klass | Syfte |
|---|---|
Vector2 | 2D floating-point vector (UV coordinates) |
Vector3 | 3D double-precision vector (positions, normals) |
Vector4 | 4D double-precision vector (homogeneous coordinates) |
FVector3 | 3D single-precision vector (compact storage) |
Quaternion | Rotationsrepresentation utan gimbal lock |
Matrix4 | 4×4 transformation matrix |
BoundingBox | Axeljusterad avgränsningsbox med min/max-hörn |
Arbeta med transformationer
from aspose.threed.utilities import Vector3, Quaternion, Matrix4
import math
##Build a rotation quaternion from axis-angle
axis = Vector3(0.0, 1.0, 0.0) # Y-axis
angle_rad = math.radians(45.0)
q = Quaternion.from_angle_axis(angle_rad, axis)
print(f"Quaternion: x={q.x:.4f} y={q.y:.4f} z={q.z:.4f} w={q.w:.4f}")
##Convert to rotation matrix
mat = q.to_matrix()
print(f"Rotation matrix row 0: {mat[0, 0]:.4f} {mat[0, 1]:.4f} {mat[0, 2]:.4f}")Beräkna en omslutningsbox
from aspose.threed import Scene
scene = Scene.from_file("model.stl")
# NOTE: mesh.get_bounding_box() is a stub — it always returns an empty BoundingBox()
# regardless of geometry. Compute bounds manually from control_points:
for node in scene.root_node.child_nodes:
if node.entity is None:
continue
mesh = node.entity
pts = mesh.control_points # returns a copy of the vertex list
if not pts:
continue
xs = [p.x for p in pts]
ys = [p.y for p in pts]
zs = [p.z for p in pts]
print(f"Mesh: {node.name}")
print(f" Min: ({min(xs):.3f}, {min(ys):.3f}, {min(zs):.3f})")
print(f" Max: ({max(xs):.3f}, {max(ys):.3f}, {max(zs):.3f})")Animation
Aspose.3D FOSS tillhandahåller en animationsmodell baserad på AnimationClip, AnimationNode, KeyFrame, och KeyframeSequence. Animationsdata lagrad i inlästa filer (glTF, COLLADA) är åtkomlig via dessa objekt.
Läsa animationsklipp
from aspose.threed import Scene
scene = Scene.from_file("animated.glb")
for clip in scene.animation_clips:
print(f"Clip: {clip.name} ({clip.start:.2f}s – {clip.stop:.2f}s)")
for anim_node in clip.animations:
print(f" Animation node: {anim_node.name}")
for sub in anim_node.sub_animations:
print(f" Sub-animation: {sub.name}")
for bp in anim_node.bind_points:
print(f" Bind point: {bp.name}")Läs- och sparaalternativ
Varje stödd format har en motsvarande alternativklass som styr parsning och serialiseringsbeteende.
| Klass | Format | Nyckelegenskaper |
|---|---|---|
ObjLoadOptions | OBJ | enable_materials, flip_coordinate_system, normalize_normal, scale |
StlSaveOptions | STL | Binär vs. ASCII-utmatningsläge |
| (glTF använder standardinställningar) | glTF / GLB | Scengraf och material bevaras automatiskt |
Exempel på användning
Exempel 1: OBJ till STL-formatkonvertering
Konvertera en OBJ-fil (med material) till binär STL, och skriv ut mesh-statistik under processen:
from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptions
from aspose.threed.formats import StlSaveOptions
##Load OBJ with material support
load_opts = ObjLoadOptions()
load_opts.enable_materials = True
load_opts.flip_coordinate_system = False
load_opts.normalize_normal = True
scene = Scene()
scene.open("input.obj", load_opts)
##Report what was loaded
total_vertices = 0
total_polygons = 0
for node in scene.root_node.child_nodes:
if node.entity is not None:
mesh = node.entity
total_vertices += len(mesh.control_points)
total_polygons += len(mesh.polygons)
print(f" {node.name}: {len(mesh.control_points)} vertices, {len(mesh.polygons)} polygons")
print(f"Total: {total_vertices} vertices, {total_polygons} polygons")
##Save as STL
save_opts = StlSaveOptions()
scene.save("output.stl", save_opts)
print("Saved output.stl")Exempel 2: Batch glTF till GLB-paketering
Spara om en katalog med separata glTF- + texturfiler som självständiga GLB-binärer:
import os
from aspose.threed import Scene
input_dir = "gltf_files"
output_dir = "glb_files"
os.makedirs(output_dir, exist_ok=True)
for filename in os.listdir(input_dir):
if not filename.endswith(".gltf"):
continue
src = os.path.join(input_dir, filename)
dst = os.path.join(output_dir, filename.replace(".gltf", ".glb"))
scene = Scene.from_file(src)
scene.save(dst)
print(f"Packed {filename} -> {os.path.basename(dst)}")Exempel 3: Inspektion av scengraf och exportrapport
Gå igenom en COLLADA-fils scengraf, samla in per-mesh-statistik och skriv ut en strukturerad rapport:
from aspose.threed import Scene
scene = Scene.from_file("assembly.dae")
report = []
def collect(node, path=""):
full_path = f"{path}/{node.name}" if node.name else path
if node.entity is not None:
mesh = node.entity
gt = node.global_transform
report.append({
"path": full_path,
"vertices": len(mesh.control_points),
"polygons": len(mesh.polygons),
"world_x": gt.translation.x,
"world_y": gt.translation.y,
"world_z": gt.translation.z,
})
for child in node.child_nodes:
collect(child, full_path)
collect(scene.root_node)
print(f"{'Path':<40} {'Verts':>6} {'Polys':>6} {'X':>8} {'Y':>8} {'Z':>8}")
print("-" * 78)
for entry in report:
print(
f"{entry['path']:<40} "
f"{entry['vertices']:>6} "
f"{entry['polygons']:>6} "
f"{entry['world_x']:>8.3f} "
f"{entry['world_y']:>8.3f} "
f"{entry['world_z']:>8.3f}"
)Tips och bästa praxis
Val av format
- glTF 2.0 / GLB är det rekommenderade utbytesformatet för scener som innehåller material, animationer och komplexa hierarkier. Föredra GLB (binär) framför glTF (text + externa filer) för portabilitet.
- STL är det rätta valet när den nedströms konsumenten är en slicer, CAD-verktyg eller något verktyg som bara behöver geometri. STL innehåller ingen material- eller animationsdata.
- OBJ stöds brett och är ett bra val när materialdata måste utbytas med äldre verktyg. Behåll alltid .mtl-filen tillsammans med .obj-filen.
Koordinatsystem
- Olika applikationer använder olika handhetskonventioner. Ställ in
ObjLoadOptions.flip_coordinate_system = Truevid import av OBJ-filer från verktyg som använder ett högrehandskoordinatsystem om din pipeline förväntar sig vänsterhandskoordinater, och vice versa. - Verifiera axelkonventionen för källresursen innan du tillämpar någon vändning. Att vända två gånger ger felaktig geometri.
Normalisering
- Ställ alltid in
ObjLoadOptions.normalize_normal = Truenär den nedströms pipeline förväntar sig enhetsnormaler (t.ex. när normaller skickas till en shader eller vid beräkning av punktproduktbelysning). Onormaliserade normaller från dåligt formade OBJ-filer orsakar belysningsartefakter.
Prestanda
- Läs in filer en gång och transformera scengrafen i minnet istället för att läsa om från disk för varje utdataformat. En enda
Scene.from_file()anrop följt av flerascene.save()anrop är mer effektivt än upprepade inläsningar. - När du bearbetar stora batcher, konstruera en enda
ObjLoadOptionsellerStlSaveOptionsinstans och återanvänd den för alla filer istället för att konstruera ett nytt alternativobjekt per fil.
Felhantering
- Omslut
scene.open()ochscene.save()anrop itry/exceptblock när du bearbetar opålitliga eller användargenererade filer. Rapportera filnamnet i undantagsmeddelanden för att förenkla felsökning i batch-pipelines.
Vanliga problem
| Problem | Orsak | Lösning |
|---|---|---|
| Mesh visas spegelvänd efter inläsning | Mismatch i koordinatsystemets handhet | Växla ObjLoadOptions.flip_coordinate_system |
| Normaler har noll längd | Källfilen har icke-normaliserade normaler | Inställning ObjLoadOptions.normalize_normal = True |
| Materialen laddas inte från OBJ | enable_materials är False (standard) | Inställning ObjLoadOptions.enable_materials = True |
| Scenen laddas men alla noder är tomma | Filen använder FBX-format | FBX-tolken är under utveckling; använd OBJ, STL eller glTF istället |
| Modellen är extremt liten eller stor | Källfilen använder icke-metriska enheter | Tillämpa ObjLoadOptions.scale för att konvertera till din målenhet |
AttributeError på mesh.polygons | Nodentity är inte ett Mesh | Skydda med if node.entity is not None innan du får åtkomst till entity‑egenskaper |
| GLB‑filen avvisas av visaren | Sparad med .gltf filändelse | Använd .glb filändelse när du anropar scene.save() för att utlösa binär behållare |
Vanliga frågor
Vilka Python-versioner stöds? Python 3.7, 3.8, 3.9, 3.10, 3.11 och 3.12 stöds alla. Biblioteket är ren Python utan någon inbyggd extension, så det fungerar på alla plattformar där CPython körs.
Har biblioteket några externa beroenden? Nej. Aspose.3D FOSS för Python använder endast Pythons standardbibliotek. Det installeras som ett enda pip install aspose-3d-foss kommando utan några efterföljande steg.
Stöds FBX? FBX-tokeniseraren är implementerad och kan parsra den binära FBX-tokenströmmen, men scengrafbyggaren ovanpå tokeniseraren har kända buggar och är inte produktionsklar. Använd OBJ, STL, glTF, COLLADA eller 3MF för pålitlig produktionsanvändning.
Kan jag använda Aspose.3D FOSS i en kommersiell produkt? Ja. Biblioteket är släppt under MIT-licensen, som tillåter användning i proprietär och kommersiell programvara utan royaltybetalningar, förutsatt att licensmeddelandet inkluderas.
Hur rapporterar jag en bugg eller begär ett format? Öppna ett ärende i arkivet. Inkludera en minimal reproduktionsfil och Python-versionen, operativsystemet och biblioteks versionen från pip show aspose-3d-foss.
API-referenssammanfattning
Kärnklasser
Scene: Överordnad behållare för en 3D-scen. Ingångspunkt föropen(),from_file(), ochsave().Node: Trädnod i scengrafen. Bärentity,transform,global_transform,material,child_nodes, ochname.Entity: Basklass för objekt som är fästa vid noder (Mesh, Camera, Light).Transform: Lokalrumslig position, rotation (Quaternion) och skala för en nod.GlobalTransform: Endast läsbar världsrumstransform beräknad genom att ackumulera alla föräldratransformer.
Geometri
Mesh: Polygonmesh medcontrol_points(vertexlista) ochpolygons.VertexElementNormal: Per-vertex- eller per-polygonnormala vektorer.VertexElementUV: Per-vertex UV-teksturkoordinater.VertexElementVertexColor: Per-vertex färgdata.VertexElementSmoothingGroup: Polygonutjämningsgruppstilldelningar.
Material
LambertMaterial: Diffus skuggningsmodell meddiffuse_colorochemissive_color.PhongMaterial: Lägger till spekulär skuggningsmodellspecular_colorochshininess.
Matematiska verktyg (aspose.threed.utilities)
Vector2: 2D-vektor.Vector3: 3D dubbelprecision vektor.Vector4: 4D dubbelprecision vektor.FVector3: 3D enkelprecision vektor.Quaternion: Rotationskvaternion medfrom_angle_axis(): ochto_matrix().Matrix4: 4×4 transformationsmatris.BoundingBox: Axeljusterad begränsningsbox medminimum: ochmaximum: hörn.
Animation
AnimationClip: Namngiven behållare för en uppsättning animationskanaler och deras nyckelramar.AnimationNode: Per-nod animationsdata inom ett klipp.KeyFrame: Enskild nyckelram med tid och värde.KeyframeSequence: Ordnad sekvens av nyckelramar för en enskild animerad egenskap.
Laddnings- / sparalternativ
ObjLoadOptions: OBJ-specifika laddningsinställningar:enable_materials,flip_coordinate_system,normalize_normal,scale.StlSaveOptions: STL-specifika sparinställningar (binärt vs. ASCII-läge).
Kameror och ljus
Camera: Kameraenhet med projektioninställningar, kan fästas på enNode.Light: Ljuskällaenhet, som kan fästas på enNode.