Funkce a vlastnosti

Aspose.3D FOSS pro Python poskytuje kompletní API pro scénový graf pro čtení, vytváření a zápis 3D obsahu v několika průmyslových standardních formátech. Tato stránka dokumentuje každou hlavní oblast funkcí s funkčními příklady kódu Python, které používají skutečné API knihovny.

Instalace a nastavení

Nainstalujte knihovnu z PyPI jedním příkazem:

pip install aspose-3d-foss

Nejsou vyžadovány žádné další systémové balíčky, nativní rozšíření ani kompilátorské toolchainy. Knihovna je čistý Python a podporuje Python 3.7 až 3.12 na Windows, macOS a Linuxu.

Pro ověření instalace:

from aspose.threed import Scene

scene = Scene()
print("Aspose.3D FOSS installed successfully")
print(f"Root node name: {scene.root_node.name}")

Funkce a vlastnosti

Podpora formátů

Aspose.3D FOSS pro Python čte a zapisuje následující formáty:

FormátPříponaČístZapisovatPoznámky
Wavefront OBJ.objAnoAno.Načítání materiálu .mtl podporováno
STL (binární).stlAnoAnoRoundtrip ověřeno (39 testů)
STL (ASCII).stlAnoAnoRoundtrip ověřeno
glTF 2.0.gltfAnoAnoCelý graf scény zachován
GLB (binární glTF).glbAnoAnoJednosouborový binární kontejner
COLLADA.daeAnoAnoHierarchie scény a materiály
3MF.3mfAnoAnoFormát aditivní výroby
FBX.fbxČástečnýNeTokenizer funguje; parser má známé chyby

Načítání OBJ s volbami

ObjLoadOptions řídí, jak jsou soubory OBJ parsovány:

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

Ukládání do STL

StlSaveOptions řídí binární vs. ASCII výstup a další nastavení specifická pro STL:

from aspose.threed import Scene
from aspose.threed.formats import StlSaveOptions

scene = Scene.from_file("model.obj")
options = StlSaveOptions()
scene.save("output.stl", options)

Scénový graf

Veškerý 3D obsah je organizován jako strom of Node objekty. Kořen stromu je scene.root_node. Každý uzel může obsahovat podřízené uzly a nést Entity (mesh, kamera nebo světlo) plus a Transform.

Procházení hierarchie scény

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)

Programové vytváření scény

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

Prohlížení GlobalTransform

GlobalTransform udává transformaci v světovém prostoru uzlu po akumulaci všech transformací předků:

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

The Mesh entita poskytuje přístup k geometrickým datům včetně řídicích bodů (vrcholů), polygonů a vrcholových prvků pro normály, UV a barvy.

Čtení geometrie Meshu

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

Přístup k prvkům vrcholů

Prvky vrcholů nesou data na úrovni vrcholu nebo polygonu. Nejčastějšími prvky jsou normály, UV souřadnice, barvy vrcholů a skupiny vyhlazování:

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

Systém materiálů

Aspose.3D FOSS podporuje dva typy materiálů: LambertMaterial (difúzní stínování) a PhongMaterial (speculární stínování). Oba jsou načteny automaticky ze souborů .mtl při použití ObjLoadOptions s enable_materials = True.

Čtení materiálů z 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}")

Programové přiřazení materiálu

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

Matematické utility

The aspose.threed.utilities modul poskytuje všechny geometrické matematické typy potřebné pro tvorbu a inspekci scény.

TřídaÚčel
Vector22D floating-point vector (UV coordinates)
Vector33D double-precision vector (positions, normals)
Vector44D double-precision vector (homogeneous coordinates)
FVector33D single-precision vector (compact storage)
QuaternionReprezentace rotace bez gimbal locku
Matrix44×4 transformation matrix
BoundingBoxosově zarovnaný ohraničující kvádr s rohy min/max

Práce s transformacemi

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

Výpočet ohraničujícího boxu

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

Animace

Aspose.3D FOSS poskytuje animační model založený na AnimationClip, AnimationNode, KeyFrame, a KeyframeSequence. Data animace uložená v načtených souborech (glTF, COLLADA) je přístupná prostřednictvím těchto objektů.

Čtení animačních klipů

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

Možnosti načítání a ukládání

Každý podporovaný formát má odpovídající třídu možností, která řídí chování při parsování a serializaci.

TřídaFormátKlíčové vlastnosti
ObjLoadOptionsOBJenable_materials, flip_coordinate_system, normalize_normal, scale
StlSaveOptionsSTLBinární vs. ASCII režim výstupu
(glTF používá výchozí hodnoty)glTF / GLBGraf scény a materiály jsou automaticky zachovány

Příklady použití

Příklad 1: Konverze formátu OBJ na STL

Převést soubor OBJ (s materiály) na binární STL a během toho vypisovat statistiky sítě:

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

Příklad 2: Dávkové balení glTF do GLB

Znovu uložit adresář samostatných souborů glTF + textur jako samostatné binární soubory GLB:

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

Příklad 3: Inspekce grafu scény a exportní zpráva

Procházet graf scény souboru COLLADA, sbírat statistiky pro každou síť a vytisknout strukturovanou zprávu:

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

Tipy a osvědčené postupy

Výběr formátu

  • glTF 2.0 / GLB je doporučený výměnný formát pro scény, které zahrnují materiály, animace a složité hierarchie. Upřednostněte GLB (binární) před glTF (text + externí soubory) pro přenositelnost.
  • STL je správnou volbou, když je koncovým uživatelem slicer, CAD nástroj nebo jakýkoli nástroj, který potřebuje jen geometrii. STL neobsahuje žádná data o materiálech ani animacích.
  • OBJ je široce podporován a je dobrá volba, když je třeba vyměňovat data o materiálech se staršími nástroji. Vždy uchovávejte soubor .mtl vedle souboru .obj.

Systémy souřadnic

  • Různé aplikace používají různé konvence pravotočivosti. Nastavte ObjLoadOptions.flip_coordinate_system = True při importu OBJ souborů z nástrojů, které používají pravotočivý souřadnicový systém, pokud váš pipeline očekává levotočivé souřadnice, a naopak.
  • Ověřte konvenci os zdrojového assetu před aplikací jakéhokoli převrácení. Dvojité převrácení vede k nesprávné geometrii.

Normalizace

  • Vždy nastavte ObjLoadOptions.normalize_normal = True pokud koncová pipeline očekává jednotkové normály (například při předávání normálů shaderu nebo při výpočtech osvětlení pomocí skalárního součinu). Nenormované normály z špatně vytvořených OBJ souborů způsobují artefakty osvětlení.

Výkon

  • Načtěte soubory jednou a transformujte graf scény v paměti místo opětovného načítání z disku pro každý výstupní formát. Jedna Scene.from_file() volání následované více scene.save() volání je efektivnější než opakované načítání.
  • Při zpracování velkých dávek vytvořte jediný ObjLoadOptions nebo StlSaveOptions instanci a znovu ji použijte ve všech souborech místo vytváření nového objektu možností pro každý soubor.

Zpracování chyb

  • Zabalit scene.open() a scene.save() volání v try/except bloky při zpracování nedůvěryhodných nebo uživatelem dodaných souborů. Uveďte název souboru ve zprávách výjimek, aby se usnadnilo ladění v dávkových pipelinech.

Běžné problémy

ProblémPříčinaŘešení
Síť se po načtení jeví jako zrcadlenáNeshoda orientace souřadnicového systémuPřepnout ObjLoadOptions.flip_coordinate_system
Normály mají nulovou délkuZdrojový soubor obsahuje nenormalizované normályNastavit ObjLoadOptions.normalize_normal = True
Materiály nebyly načteny z OBJenable_materials je False (výchozí)Nastavit ObjLoadOptions.enable_materials = True
Scéna se načte, ale všechny uzly jsou prázdnéSoubor používá formát FBXParser FBX je ve vývoji; místo toho použijte OBJ, STL nebo glTF
Model je extrémně malý nebo velkýZdrojový soubor používá nemetrické jednotkyPoužít ObjLoadOptions.scale k převodu na cílovou jednotku
AttributeError zapnuto mesh.polygonsEntita uzlu není MeshChraňte pomocí if node.entity is not None před přístupem k vlastnostem entity
Soubor GLB byl odmítnut prohlížečemUloženo s .gltf příponouPoužijte .glb příponu při volání scene.save() k vyvolání binárního kontejneru

Často kladené otázky

Jaké verze Python jsou podporovány? Python 3.7, 3.8, 3.9, 3.10, 3.11 a 3.12 jsou všechny podporovány. Knihovna je čistý Python bez nativních rozšíření, takže funguje na jakékoli platformě, kde běží CPython.

Má knihovna nějaké externí závislosti? Ne. Aspose.3D FOSS pro Python používá pouze standardní knihovnu Python. Instalace probíhá jako jediný pip install aspose-3d-foss příkaz bez dalších kroků.

Je FBX podporováno? Tokenizér FBX je implementován a dokáže parsovat binární tokenový proud FBX, ale scene-graph builder nad tokenizérem má známé chyby a není připraven pro produkční nasazení. Použijte OBJ, STL, glTF, COLLADA nebo 3MF pro spolehlivé produkční použití.

Mohu použít Aspose.3D FOSS v komerčním produktu? Ano. Knihovna je vydána pod licencí MIT, která umožňuje použití v proprietárním a komerčním softwaru bez licenčních poplatků, pokud je zahrnuto oznámení o licenci.

Jak mohu nahlásit chybu nebo požádat o formát? Otevřete issue v repozitáři. Přiložte minimální reprodukční soubor a verzi Python, operační systém a verzi knihovny z pip show aspose-3d-foss.


Shrnutí referenčního API

Základní třídy

  • Scene: Nadřazený kontejner pro 3D scénu. Vstupní bod pro open(), from_file(), a save().
  • Node: Uzel stromu v grafu scény. Nese entity, transform, global_transform, material, child_nodes, a name.
  • Entity: Základní třída pro objekty připojené k uzlům (Mesh, Camera, Light).
  • Transform: Lokální pozice, rotace (Quaternion) a měřítko uzlu.
  • GlobalTransform: Pouze pro čtení transformace ve světovém prostoru vypočtená akumulací všech transformací předků.

Geometrie

  • Mesh: Polygonální síť s control_points (seznam vrcholů) a polygons.
  • VertexElementNormal: Normálové vektory na vrchol nebo na polygon.
  • VertexElementUV: UV texturové souřadnice na vrchol.
  • VertexElementVertexColor: Barevná data na vrchol.
  • VertexElementSmoothingGroup: Přiřazení skupin vyhlazování polygonů.

Materiály

  • LambertMaterial: Difúzní model osvětlení s diffuse_color a emissive_color.
  • PhongMaterial: Přidání spekulárního modelu stínování specular_color a shininess.

Matematické utility (aspose.threed.utilities)

  • Vector2: 2D vektor.
  • Vector3: 3D vektor s dvojitou přesností.
  • Vector4: 4D vektor s dvojitou přesností.
  • FVector3: 3D vektor s jednoduchou přesností.
  • Quaternion: Rotacní kvaternion s from_angle_axis() a to_matrix().
  • Matrix4: 4×4 transformační matice.
  • BoundingBox: Osa‑zarovnaná ohraničující krabice s minimum a maximum : rohy.

Animace

  • AnimationClip: Pojmenovaný kontejner pro sadu animačních kanálů a jejich klíčových snímků.
  • AnimationNode: Animace na úrovni uzlu v rámci klipu.
  • KeyFrame: Jednotlivý klíčový snímek s časem a hodnotou.
  • KeyframeSequence: Uspořádaná sekvence klíčových snímků pro jedinou animovanou vlastnost.

Možnosti načítání / ukládání

  • ObjLoadOptions: Nastavení načítání specifická pro OBJ: enable_materials, flip_coordinate_system, normalize_normal, scale.
  • StlSaveOptions: Nastavení ukládání specifická pro STL (binární vs. ASCII režim).

Kamery a světla

  • Camera: Entita kamery s nastavením projekce, připojitelná k a Node.
  • Light: Entita světelného zdroje, připojitelná k a Node.
 Čeština