How to Build Entities in Python
Aspose.3D for Python builds 3D geometry two ways: by instantiating a ready-made
primitive shape (Box, Sphere, Cylinder, Torus, Plane, Dish) and
converting it to a Mesh with to_mesh(), or by constructing a Mesh directly
from control points and polygons. Either way, the resulting entity is attached to
a Node in the scene graph before the scene is saved.
Step-by-Step Guide
Step 1: Install the Package
pip install aspose-3d-fossVerify the install:
python -c "import aspose.threed; print(aspose.threed.__name__)"Step 2: Import Required Classes
from aspose.threed import Scene
from aspose.threed.entities import Box, Sphere, Mesh
from aspose.threed.shading import LambertMaterial, PbrMaterial
from aspose.threed.utilities import Vector3, Vector4Step 3: Build a Primitive Entity
Primitive helper classes take their dimensions as constructor arguments and expose
a to_mesh() method that converts them into a renderable/saveable Mesh.
from aspose.threed.entities import Box
box = Box(10, 20, 30) # length, width, height
mesh = box.to_mesh()
print(f"Control points: {len(mesh.control_points)}")A Sphere works the same way, and can be shaded with a PbrMaterial in the same
step it is attached to a node:
from aspose.threed import Scene
from aspose.threed.entities import Sphere
from aspose.threed.shading import PbrMaterial
from aspose.threed.utilities import Vector3
scene = Scene()
sphere = Sphere()
material = PbrMaterial(albedo=Vector3(0.8, 0.1, 0.1))
material.metallic_factor = 0.9
material.roughness_factor = 0.2
scene.root_node.create_child_node("Ball", entity=sphere.to_mesh(), material=material)
scene.save("ball.stl")Step 4: Position and Scale with a Transform
Every Node has a transform with translation, scaling, and rotation (as a
Quaternion) properties for placing the entity in the scene:
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")Step 5: Build a Custom Mesh from Control Points
When no primitive matches the shape you need, build a Mesh directly: append
vertex positions as Vector4 entries to its control-points list, then connect them
into triangles with create_polygon().
from aspose.threed import Scene
from aspose.threed.entities import Mesh
from aspose.threed.utilities import Vector3, Vector4
from aspose.threed.shading import LambertMaterial
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)
material = LambertMaterial()
material.diffuse_color = Vector3(0.2, 0.6, 0.9)
scene.root_node.create_child_node("Triangle", entity=mesh, material=material)
scene.save("triangle.gltf")For a shape with more polygons, call create_polygon() once per face, passing
the control-point indices in winding order — twelve calls build a complete cube
from eight control points, two triangles per face.
Step 6: Attach the Entity and Material to a Node
create_child_node() combines node creation, entity attachment, and material
assignment in a single call, as used in the steps above. The equivalent longer
form, useful when the node already exists, is:
node = scene.root_node.create_child_node("Crate")
node.entity = mesh
node.material = materialCommon Issues and Fixes
to_mesh() returns an empty-looking object on a Primitive subclass with zero
segments configured. Primitive shapes such as Cylinder and Sphere expose
segment-count properties (width/height segment counts, …); leaving them at their
defaults still produces a valid mesh, but setting one to zero before calling
to_mesh() can produce a degenerate geometry. Keep segment counts at 1 or above.
Polygon winding looks inverted after create_polygon(). The order of the
indices passed to create_polygon() determines the face normal direction by the
right-hand rule. If a face appears to be facing the wrong way after export, reverse
the index order for that face.
Adding a control point raises a type error. The control-points list on Mesh
holds Vector4 entries (homogeneous coordinates), not Vector3. Always construct
the fourth component explicitly, typically the value 1.0, e.g. Vector4(x, y, z, 1.0).
Material assigned but the exported file looks untextured/flat. LambertMaterial,
PhongMaterial, and PbrMaterial all drive shading through solid colour and factor
properties in this release — texture image binding is not implemented, so a material
built only from colour and factor properties is the expected, fully supported result.
Node created but nothing appears in the saved file. Confirm the entity was
actually assigned, either via create_child_node(..., entity=mesh) or by setting
node.entity = mesh afterwards — a Node with no entity is a valid empty
transform node and will not render or show polygons in the output format.
Frequently Asked Questions
Which primitive shapes are available besides Box, Sphere, and Cylinder?
Torus, Plane, and Dish are also available as ready-made primitives, each with
its own constructor parameters and a to_mesh() method that follows the same
pattern shown above.
Can I convert a primitive to a mesh and then keep editing it?
Yes — to_mesh() returns a regular Mesh object, so after conversion you can call
create_polygon(), add_element(), or any other Mesh method on the result just as
you would on a hand-built mesh.
Do I need to call triangulate() on a mesh I built myself with triangles?
No. create_polygon() accepts any number of indices per call; if you only ever pass
three indices per call, the mesh is already fully triangulated. triangulate() is for
converting meshes that contain higher-order (quad or n-gon) polygons.
Is there a simpler way to create many identical entities?
Not a built-in batch constructor — call the primitive constructor and
create_child_node() in a loop, varying the name and the transform for each
instance.