Introduction

Aspose.3D FOSS for Python is a zero-dependency, MIT-licensed library, published on PyPI as aspose-3d-foss, for reading, writing, and converting 3D file formats. Beyond scene loading and saving, it includes a set of smaller utility classes for working with geometry and formats directly: vector types for positions and colors, a per-node transform object for placing geometry in a scene, and format classes that resolve the correct save options without hardcoding a file extension string.

This post covers those utility classes: Vector3 and Vector4 for numeric data, Transform for positioning scene nodes, and FileFormat together with the format-specific load/save option classes. These are the building blocks used across loading, saving, and geometry-construction code, independent of any single file format.

The library has no C extensions and no third-party runtime dependencies, so every example below runs with nothing installed beyond the package itself.


What’s Included

Vector3 for Color and Position Data

Vector3 is a lightweight x/y/z value type used throughout the API wherever a direction, position, or color needs three components — for example, a material’s diffuse color:

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

Node.transform for Placing Geometry

Every Node carries a Transform object with translation and scaling properties (both Vector3), used to position and size an entity without altering its underlying mesh data:

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

FileFormat for Resolving Save Options

FileFormat.get_format_by_extension() looks up a format by its file extension and returns a FileFormat instance. Pass it into a format-specific save-options constructor, such as GltfSaveOptions, to get a correctly-configured options object without hardcoding a filename. This is the pattern to use whenever you are saving to a stream rather than a named file, since scene.save() can only infer the format from a filename’s extension — a bare stream gives it nothing to detect from:

import io
import json
from aspose.threed import Scene, FileFormat
from aspose.threed.entities import Mesh
from aspose.threed.formats.gltf import GltfSaveOptions
from aspose.threed.utilities import Vector4

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)

node = scene.root_node.create_child_node("TestNode")
node.entity = mesh

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(len(gltf_data["meshes"]))

Load Options for Format-Specific Parsing

Import formats that carry extra, format-specific settings expose a dedicated load-options class. ObjLoadOptions, for example, controls whether companion .mtl material files are parsed during import:

from aspose.threed import Scene
from aspose.threed.formats.obj import ObjLoadOptions

scene = Scene()
options = ObjLoadOptions()
options.enable_materials = True
scene.open("model.obj", options)

for node in scene.root_node.child_nodes:
    if node.entity is not None:
        mesh = node.entity
        print(f"{node.name}: {len(mesh.control_points)} vertices, {mesh.polygon_count} polygons")

Quick Start

pip install aspose-3d-foss

Build a triangle from Vector4 control points, move and scale it with node.transform, then resolve glTF save options from the target extension via FileFormat instead of a filename:

import io
from aspose.threed import Scene, FileFormat
from aspose.threed.entities import Mesh
from aspose.threed.formats.gltf import GltfSaveOptions
from aspose.threed.utilities import Vector3, 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(0.0, 1.0, 0.0, 1.0))
mesh.create_polygon(0, 1, 2)

node = scene.root_node.create_child_node("Triangle", entity=mesh)
node.transform.translation = Vector3(0.0, 0.0, 2.0)
node.transform.scaling = Vector3(2.0, 2.0, 2.0)

stream = io.BytesIO()
options = GltfSaveOptions(FileFormat.get_format_by_extension(".gltf"))
options.binary_mode = False
scene.save(stream, options)

Supported Formats

FormatExtensionReadWrite
OBJ.obj✓✓
STL.stl✓✓
glTF / GLB.gltf / .glb✓✓
COLLADA.dae✓✓
3MF.3mf✓✓
FBX.fbx✓—

FBX import uses a dedicated tokenizer and parser; FBX export (FbxExporter) is not implemented in this FOSS edition. Use FileFormat.get_format_by_extension() to resolve the matching load or save options class for any of the formats above instead of hardcoding option-class names.


Open Source & Licensing

Aspose.3D FOSS for Python is released under the MIT license. You can use, modify, and redistribute it in both open-source and commercial projects without restriction. The source is available on GitHub under the Aspose organization, alongside the published package on PyPI.


Getting Started