Funktioner och funktionaliteter

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-foss

Inga 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:

FormatFiländelseLäsSkrivAnteckningar
Wavefront OBJ.objJaJa.mtl-materialladdning stöds
STL (binär).stlJaJaRundresa verifierad (39 tester)
STL (ASCII).stlJaJaRundresa verifierad
glTF 2.0.gltfJaJaFullständig scengraf bevarad
GLB (binär glTF).glbJaJaEnfilig binärbehållare
COLLADA.daeJaJaScenhierarki och material
3MF.3mfJaJaAdditivt tillverkningsformat
FBX.fbxDelvisNejTokenizer 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.

KlassSyfte
Vector22D floating-point vector (UV coordinates)
Vector33D double-precision vector (positions, normals)
Vector44D double-precision vector (homogeneous coordinates)
FVector33D single-precision vector (compact storage)
QuaternionRotationsrepresentation utan gimbal lock
Matrix44×4 transformation matrix
BoundingBoxAxeljusterad 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.

KlassFormatNyckelegenskaper
ObjLoadOptionsOBJenable_materials, flip_coordinate_system, normalize_normal, scale
StlSaveOptionsSTLBinär vs. ASCII-utmatningsläge
(glTF använder standardinställningar)glTF / GLBScengraf 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 = True vid 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 = True nä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 flera scene.save() anrop är mer effektivt än upprepade inläsningar.
  • När du bearbetar stora batcher, konstruera en enda ObjLoadOptions eller StlSaveOptions instans och återanvänd den för alla filer istället för att konstruera ett nytt alternativobjekt per fil.

Felhantering

  • Omslut scene.open() och scene.save() anrop i try/except block 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

ProblemOrsakLösning
Mesh visas spegelvänd efter inläsningMismatch i koordinatsystemets handhetVäxla ObjLoadOptions.flip_coordinate_system
Normaler har noll längdKällfilen har icke-normaliserade normalerInställning ObjLoadOptions.normalize_normal = True
Materialen laddas inte från OBJenable_materials är False (standard)Inställning ObjLoadOptions.enable_materials = True
Scenen laddas men alla noder är tommaFilen använder FBX-formatFBX-tolken är under utveckling; använd OBJ, STL eller glTF istället
Modellen är extremt liten eller storKällfilen använder icke-metriska enheterTillämpa ObjLoadOptions.scale för att konvertera till din målenhet
AttributeErrormesh.polygonsNodentity är inte ett MeshSkydda med if node.entity is not None innan du får åtkomst till entity‑egenskaper
GLB‑filen avvisas av visarenSparad med .gltf filändelseAnvä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ör open(), from_file(), och save().
  • Node: Trädnod i scengrafen. Bär entity, transform, global_transform, material, child_nodes, och name.
  • 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 med control_points (vertexlista) och polygons.
  • VertexElementNormal: Per-vertex- eller per-polygonnormala vektorer.
  • VertexElementUV: Per-vertex UV-teksturkoordinater.
  • VertexElementVertexColor: Per-vertex färgdata.
  • VertexElementSmoothingGroup: Polygonutjämningsgruppstilldelningar.

Material

  • LambertMaterial: Diffus skuggningsmodell med diffuse_color och emissive_color.
  • PhongMaterial: Lägger till spekulär skuggningsmodell specular_color och shininess.

Matematiska verktyg (aspose.threed.utilities)

  • Vector2: 2D-vektor.
  • Vector3: 3D dubbelprecision vektor.
  • Vector4: 4D dubbelprecision vektor.
  • FVector3: 3D enkelprecision vektor.
  • Quaternion: Rotationskvaternion med from_angle_axis() : och to_matrix().
  • Matrix4: 4×4 transformationsmatris.
  • BoundingBox: Axeljusterad begränsningsbox med minimum : och maximum : 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å en Node.
  • Light: Ljuskällaenhet, som kan fästas på en Node.
 Svenska