Introduction
Aspose.3D FOSS for Python is a zero-dependency, MIT-licensed library published on PyPI
as aspose-3d-foss. Its API is distributed
under the aspose_3d_foss package and exposed through the aspose.threed namespace
used in the import statements throughout this post.
Every file the library loads, and every scene you build in code, is represented with
the same object model: a Scene holding a tree of Node objects, each node carrying a
Transform and zero or more attached Entity objects such as Mesh. This post covers
that core model directly — constructing nodes, attaching geometry, and reading back
mesh data — rather than file conversion.
This is useful whenever you need to generate or inspect 3D content programmatically: building simple geometry at runtime, walking an existing scene graph to collect statistics, or composing primitives into a larger scene before saving it out.
What’s Included
Building the Scene Graph
A Scene starts with an empty root_node. New nodes are attached under it with
create_child_node(), which accepts an entity (such as a mesh produced by a
primitive’s to_mesh()) and an optional material:
from aspose.threed import Scene
from aspose.threed.entities import Box
from aspose.threed.shading import LambertMaterial
from aspose.threed.utilities import Vector3
scene = Scene()
box = Box(length=2.0, width=1.0, height=1.0)
material = LambertMaterial()
material.diffuse_color = Vector3(0.2, 0.6, 0.9)
scene.root_node.create_child_node("Crate", entity=box.to_mesh(), material=material)
scene.save("crate.gltf")
Mesh and Polygon Data
A Mesh stores geometry as a control_points list of Vector4 positions and a set of
polygons built by index with create_polygon(). This is the lowest-level way to build
or inspect geometry, independent of any file format:
from aspose.threed import Scene
from aspose.threed.entities import Mesh
from aspose.threed.utilities import Vector4
scene = Scene()
mesh = Mesh("triangle")
mesh.control_points.add(Vector4(0.0, 0.0, 0.0, 1.0))
mesh.control_points.add(Vector4(1.0, 0.0, 0.0, 1.0))
mesh.control_points.add(Vector4(1.0, 1.0, 0.0, 1.0))
mesh.create_polygon(0, 1, 2)
node = scene.root_node.create_child_node("triangle_node")
node.entity = mesh
print(f"control points: {len(mesh.control_points)}, polygons: {mesh.polygon_count}")
scene.save("triangle.stl")
mesh.control_points and mesh.polygon_count can also be read back from any mesh,
whether it was built in code or loaded from a file.
Node Transforms
Each Node carries a transform (a Transform object) with translation, scaling,
and rotation properties, applied independently of the node’s geometry:
from aspose.threed import Scene
from aspose.threed.entities import Cylinder
from aspose.threed.utilities import Vector3
scene = Scene()
cylinder = Cylinder()
node = scene.root_node.create_child_node("Post", entity=cylinder.to_mesh())
node.transform.translation = Vector3(0.0, 1.0, 0.0)
node.transform.scaling = Vector3(0.5, 2.0, 0.5)
scene.save("post.obj")
Traversing the Node Hierarchy
Because every scene — built in code or loaded from a file — shares the same Node
tree, the same recursive walk works regardless of the source:
from aspose.threed import Scene
scene = Scene()
scene.open("model.gltf")
def walk(node, depth=0):
print(" " * depth + (node.name or "(unnamed)"))
for child in node.child_nodes:
walk(child, depth + 1)
walk(scene.root_node)
node.entity (or the node.entities list, for nodes with more than one attachment)
gives access to whatever Mesh or other entity a node carries while walking the tree.
Quick Start
pip install aspose-3d-fossBuild a one-triangle mesh with a PBR material, attach it to a new node, and write it out as glTF:
import io
import json
from aspose.threed import Scene, FileFormat
from aspose.threed.entities import Mesh
from aspose.threed.utilities import Vector3, Vector4
from aspose.threed.formats.gltf import GltfSaveOptions
from aspose.threed.shading import PbrMaterial
scene = Scene()
mesh = Mesh("TestMesh")
mesh.control_points.add(Vector4(0.0, 0.0, 0.0, 1.0))
mesh.control_points.add(Vector4(1.0, 0.0, 0.0, 1.0))
mesh.control_points.add(Vector4(0.0, 1.0, 0.0, 1.0))
mesh.create_polygon(0, 1, 2)
albedo = Vector3(0.8, 0.2, 0.3)
material = PbrMaterial("RedMaterial", albedo)
material.metallic_factor = 0.5
material.roughness_factor = 0.7
node = scene.root_node.create_child_node("TestNode")
node.entity = mesh
node.material = material
stream = io.BytesIO()
options = GltfSaveOptions(FileFormat.get_format_by_extension(".gltf"))
options.binary_mode = False
scene.save(stream, options)
stream.seek(0)
gltf_data = json.loads(stream.read().decode("utf-8"))
print(gltf_data["materials"][0]["pbrMetallicRoughness"])
Supported Formats
| Format | Extension(s) | Load | Save | Notes |
|---|---|---|---|---|
| OBJ | .obj | Yes | Yes | .mtl material loading supported |
| STL | .stl | Yes | Yes | Binary and ASCII; coordinate-system flip option |
| glTF | .gltf, .glb | Yes | Yes | .glb (self-contained binary) supported |
| COLLADA | .dae | Yes | Yes | ColladaSaveOptions available with flip_coordinate_system, enable_materials, indented |
| 3MF | .3mf | Yes | Yes | Suitable for 3D printing workflows |
| FBX | .fbx | Partial | N/A | Tokenizer only; full parser in progress |
The Scene/Node/Mesh object model described above is the same across every format in this table — only the loader or exporter for a given format changes.
Open Source & Licensing
Aspose.3D FOSS for Python is MIT licensed. You can use it in commercial applications, modify it, and redistribute it without restriction. The source is available on GitHub under the Aspose organisation, and the package is published on PyPI.