Skip to main content

Library for building gltf files, handling buffers, views, and accessors.

Project description

GTLF Builder

This library wraps the pygltflib library to handle the low-level details of managing buffers, buffer views, and accessors.

In this document, we will generalliy refer to the pygltflib library with the gltf orefix.

You start by creating a Builder instance. There are abstract types corresponding to the major classes from the pygltflib library, with names prepended with 'B'. For example, this library supplies a BNode class that plays the same role as gltf.Node. These classe are compiled to the corresponding gltf clases with the compile(Builder) method.

The BXxxxx names are abstract; the implementation classes bear names like _Xxxxx.

Compilation and collection of the pieces is performed by the Builder.build() method.

Quaternions

Because pygltflib uses quaternions of the form (X, Y, Z, W) instead of the form (W, X, Y, Z) used by scipy, and to avoid introducing heavyweight and potentially incompatible libraries, we provided (courtesy of ChatGPT to my specifications) an implementation of various quaternion routines relating to rotations.

Basic usage

import gltf_builder.quaternion as quat

# Rotate around Z axis by pi/2 
rotation = quat.from_axis_angle((0, 0, 1), math.py / 4)
# Instantiate a geometry, rotated.
root_node.instantiate(cube, rotation=rotation)

See quaternion.md or quaternion.py for more information.

Usage

Install via your usual tool (I recommend uv as the modern upgrade from pip and others).

from gltf_builder import Builder, PrimitiveMode

CUBE = (
    (0, 0, 0), (0, 0, 1), (0, 1, 1), (0, 1, 0),
    (1, 0, 0), (1, 0, 1), (1, 1, 1), (1, 1, 0),
)
CUBE_FACE1 = (0, 1, 2, 3)
CUBE_FACE2 = (4, 5, 6, 7)
CUBE_FACE3 = (0, 4, 5, 1)
CUBE_FACE4 = (0, 4, 7, 3)
CUBE_FACE5 = (1, 2, 6, 5)
CUBE_FACE6 = (1, 5, 6, 2)

builder = Builder()

mesh = builder.add_mesh('CUBE')
mesh.add_primitive(PrimitiveMode.LINE_LOOP, *[CUBE[i] for i in CUBE_FACE1])
mesh.add_primitive(PrimitiveMode.LINE_LOOP, *[CUBE[i] for i in CUBE_FACE2])
mesh.add_primitive(PrimitiveMode.LINE_LOOP, *[CUBE[i] for i in CUBE_FACE3])
mesh.add_primitive(PrimitiveMode.LINE_LOOP, *[CUBE[i] for i in CUBE_FACE4])
mesh.add_primitive(PrimitiveMode.LINE_LOOP, *[CUBE[i] for i in CUBE_FACE5])
mesh.add_primitive(PrimitiveMode.LINE_LOOP, *[CUBE[i] for i in CUBE_FACE6])
top = builder.add_node(name='TOP')
cube = builder.add_node(name='CUBE',
                        mesh=mesh,
                        translation=(-0.5, -0.5, -0.5),
                        detached=True, # Don't make it part of the scene
)
# Instantiate it at the origin
top.instantiate(cube)
# Instantiate it translated, scaled, and rotated.
top.instantiate(cube,
                translation=(2, 0, 0),
                scale=(1, 2, 2),
                rotation=(0.47415988, -0.40342268,  0.73846026,  0.25903472)
            )
gltf = builder.build()
gltf.save_binary('cube.glb')

The builder.build() method produces a regular pygltflib.GLTF2 instance.

To create hierarchy, use the add_node() method on a parent node.

Note that referencing the same tuple for a point treats it as the same vertex, while a copy will create a separate vertex.

Instancing

Simple instancing can be done by simply using the same mesh for multiple nodes.

You can also instance a node hierarchy with the instantiate method. This takes a node and copies it, optionally supplying a transformation.

The node can be an existing node in the scene, or it cn be created with the detached=True option to add_node(), which creates the a node that is not added to the scene. You can then use this as the root of an instancable tree, and add child nodes and meshes.

You can access existing nodes by name by the builder[name] syntax. If nodes with the same name appear in different places, you may need to first access a parent that holds only one of the duplicates. Alternatively, you can loop over all nodes like this:

builder = Builder()
# Add a bunch of nodes
...
# Print the names of every node in the tree
for node in builder:
    print(f'node={node.name}')

# Get a list of all nodes named 'Fred'
fred = [n for n in builder if n.name == 'Fred']

Still Needed

  • Tangents and other attributes (implemented but no tested)
  • Materials
  • Skins
  • Textures

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gltf_builder-0.1.8.tar.gz (41.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gltf_builder-0.1.8-py3-none-any.whl (26.4 kB view details)

Uploaded Python 3

File details

Details for the file gltf_builder-0.1.8.tar.gz.

File metadata

  • Download URL: gltf_builder-0.1.8.tar.gz
  • Upload date:
  • Size: 41.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.6.6

File hashes

Hashes for gltf_builder-0.1.8.tar.gz
Algorithm Hash digest
SHA256 0f10491f8c8cff167cf3d04db78d3b0af646a666e7b186c25501a3e0e5c19718
MD5 a376bd7f0c2f3e3bdb19a0774da25401
BLAKE2b-256 2526c358dc0269475ea64fcf1d009a6ae51e010e8b3b21954e86e047e7586513

See more details on using hashes here.

File details

Details for the file gltf_builder-0.1.8-py3-none-any.whl.

File metadata

File hashes

Hashes for gltf_builder-0.1.8-py3-none-any.whl
Algorithm Hash digest
SHA256 a8f771b65a835d7a814c63a9e676f618113bc96bc6002d14072dffe4bb8bb5fc
MD5 379e1423b40c614fb27c6b95f155eba7
BLAKE2b-256 4dfc1b14e1530358b2d85c516825feeed63955706efad9ab6db1869f0fccb6b2

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page