### Install pygltflib Source: https://github.com/avaturn/pygltflib/blob/master/README.md Standard installation commands for the library. ```bash pip install pygltflib ``` ```bash py -m pip install pygltflib ``` -------------------------------- ### Install pygltflib Source: https://github.com/avaturn/pygltflib/blob/master/README.md Install the library using pip. ```bash pip install pygltflib ``` -------------------------------- ### Create an empty GLTF2 object Source: https://github.com/avaturn/pygltflib/blob/master/README.md Initialize an empty GLTF2 object to start building a GLTF file from scratch. ```python from pygltflib import GLTF2 gltf = GLTF2() ``` -------------------------------- ### Compiled mesh writing example Source: https://github.com/avaturn/pygltflib/blob/master/README.md Alternative approach for defining GLTF2 structures with hard-coded values. ```python gltf = pygltflib.GLTF2( scene=0, scenes=[pygltflib.Scene(nodes=[0])], nodes=[pygltflib.Node(mesh=0)], meshes=[ pygltflib.Mesh( primitives=[ pygltflib.Primitive( attributes=pygltflib.Attributes(POSITION=1), indices=0 ) ] ) ], accessors=[ pygltflib.Accessor( bufferView=0, componentType=pygltflib.UNSIGNED_BYTE, count=36, type=pygltflib.SCALAR, max=[7], min=[0], ), pygltflib.Accessor( bufferView=1, componentType=pygltflib.FLOAT, count=8, type=pygltflib.VEC3, max=[0.5, 0.5, 0.5], min=[-0.5, -0.5, -0.5], ), ], bufferViews=[ pygltflib.BufferView( buffer=0, byteLength=36, target=pygltflib.ELEMENT_ARRAY_BUFFER ), pygltflib.BufferView( buffer=0, byteOffset=36, byteLength=96, target=pygltflib.ARRAY_BUFFER, ), ], buffers=[pygltflib.Buffer(byteLength=132)], ) ``` -------------------------------- ### Set Binary Blob Source: https://github.com/avaturn/pygltflib/blob/master/README.md Example of setting a binary blob on a GLTF object. ```python gltf.set_binary_blob( b"\x00\x01\x02\x03\x02\x01\x01\x00\x04\x05\x04\x00\x03\x01\x06\x04\x06\x01" b"\x02\x03\x07\x06\x07\x03\x00\x02\x05\x07\x05\x02\x05\x07\x04\x06\x04\x07" b"\x00\x00\x00\xbf\x00\x00\x00\xbf\x00\x00\x00?\x00\x00\x00?\x00\x00\x00" b"\xbf\x00\x00\x00?\x00\x00\x00\xbf\x00\x00\x00?\x00\x00\x00?\x00\x00\x00?" b"\x00\x00\x00?\x00\x00\x00?\x00\x00\x00?\x00\x00\x00\xbf\x00\x00\x00\xbf" b"\x00\x00\x00\xbf\x00\x00\x00\xbf\x00\x00\x00\xbf\x00\x00\x00?\x00\x00" b"\x00?\x00\x00\x00\xbf\x00\x00\x00\xbf\x00\x00\x00?\x00\x00\x00\xbf" ) ``` -------------------------------- ### Manage custom mesh attributes Source: https://context7.com/avaturn/pygltflib/llms.txt Illustrates how to access standard attributes and define custom vertex attributes starting with an underscore. ```python from pygltflib import GLTF2, Attributes, Accessor, BufferView, FLOAT, VEC3 gltf = GLTF2().load("model.gltf") # Access standard attributes primitive = gltf.meshes[0].primitives[0] attrs = primitive.attributes print(f"Position accessor: {attrs.POSITION}") print(f"Normal accessor: {attrs.NORMAL}") print(f"TexCoord accessor: {attrs.TEXCOORD_0}") # Add custom attribute attrs._TEMPERATURE = len(gltf.accessors) # Index to new accessor attrs._CUSTOM_COLOR = len(gltf.accessors) + 1 # Custom attributes can be set dynamically setattr(attrs, "_VELOCITY", len(gltf.accessors) + 2) # Create new Attributes with custom fields custom_attrs = Attributes( POSITION=0, NORMAL=1, _MYCUSTOMDATA=2 ) print(f"Custom attributes: {custom_attrs}") # Access all attribute fields for attr_name, accessor_index in primitive.attributes.__dict__.items(): if accessor_index is not None: print(f"{attr_name}: accessor {accessor_index}") ``` -------------------------------- ### Add custom attributes Source: https://github.com/avaturn/pygltflib/blob/master/README.md Adds application-specific attributes to mesh primitives. Custom semantics must start with an underscore. ```python # Application-specific semantics must start with an underscore, e.g., _TEMPERATURE. a = Attributes() a._MYCUSTOMATTRIBUTE = 123 gltf.meshes[0].primitives[0].attributes._MYOTHERATTRIBUTE = 456 ``` -------------------------------- ### Load and Save GLB Files Source: https://github.com/avaturn/pygltflib/blob/master/README.md Demonstrates loading a GLB file, inspecting its properties, and saving it. ```python >>> from pygltflib import GLTF2 >>> glb_filename = "glTF-Sample-Models/2.0/Box/glTF-Binary/Box.glb" >>> glb = GLTF2().load(glb_filename) >>> glb.scene 0 >>> glb.scenes [Scene(name='', nodes=[0])] >>> glb.nodes[0] Node(mesh=None, skin=None, rotation=[], translation=[], scale=[], children=[1], matrix=[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], camera=None, name=None) >>> glb.meshes[0].primitives[0].attributes Attributes(POSITION=2, NORMAL=1, TANGENT=None, TEXCOORD_0=None, TEXCOORD_1=None, COLOR_0=None, JOINTS_0=None, WEIGHTS_0=None) >>> glb.save("test.glb") >>> glb.binary_blob() # read the binary blob used by the buffer in a glb ``` -------------------------------- ### Load and Save GLTF Files Source: https://github.com/avaturn/pygltflib/blob/master/README.md Demonstrates loading a GLTF file, inspecting its properties, and saving it. ```python >>> from pygltflib import GLTF2 >>> filename = "glTF-Sample-Models/2.0/AnimatedCube/glTF/AnimatedCube.gltf" >>> gltf = GLTF2().load(filename) >>> gltf.scene 0 >>> gltf.scenes [Scene(name='', nodes=[0])] >>> gltf.nodes[0] Node(mesh=0, skin=None, rotation=[0.0, -1.0, 0.0, 0.0], translation=[], scale=[], children=[], matrix=[], camera=None, name='AnimatedCube') >>> gltf.nodes[0].name 'AnimatedCube' >>> gltf.meshes[0].primitives[0].attributes Attributes(NORMAL=4, POSITION=None, TANGENT=5, TEXCOORD_0=6) >>> filename2 = "test.gltf" >>> gltf.save(filename2) ``` -------------------------------- ### Load and Save glTF Files Source: https://context7.com/avaturn/pygltflib/llms.txt Demonstrates loading glTF files from disk or bytes using auto-detection or explicit format methods. Shows how to save glTF files in JSON or binary format, including saving to bytes. ```python from pygltflib import GLTF2 # Auto-detect and load any glTF format gltf = GLTF2().load("model.gltf") # JSON format glb = GLTF2().load("model.glb") # Binary format # Load with explicit format gltf = GLTF2.load_json("model.gltf") glb = GLTF2.load_binary("model.glb") # Load from bytes (useful for network/memory operations) with open("model.glb", "rb") as f: data = f.read() glb = GLTF2.load_from_bytes(data) # Access scene data after loading print(f"Scene count: {len(gltf.scenes)}") print(f"Active scene: {gltf.scene}") print(f"Nodes: {[node.name for node in gltf.nodes]}") print(f"Meshes: {len(gltf.meshes)}") # Save files gltf.save("output.gltf") # JSON format gltf.save("output.glb") # Binary format (auto-detected by extension) # Explicit save methods gltf.save_json("output.gltf") gltf.save_binary("output.glb") # Save to bytes for streaming/network glB_bytes = b"".join(gltf.save_to_bytes()) ``` -------------------------------- ### Manage Materials Source: https://context7.com/avaturn/pygltflib/llms.txt Inspecting and creating PBR materials for glTF models. ```python from pygltflib import ( GLTF2, Material, PbrMetallicRoughness, TextureInfo, Texture, Sampler, Image, BLEND, MASK, OPAQUE ) gltf = GLTF2().load("model.gltf") # Access existing materials for i, material in enumerate(gltf.materials): print(f"Material {i}: {material.name}") if material.pbrMetallicRoughness: pbr = material.pbrMetallicRoughness print(f" Base color: {pbr.baseColorFactor}") print(f" Metallic: {pbr.metallicFactor}") print(f" Roughness: {pbr.roughnessFactor}") print(f" Alpha mode: {material.alphaMode}") print(f" Double sided: {material.doubleSided}") # Create a new material material = Material() material.name = "Red Metal" material.pbrMetallicRoughness = PbrMetallicRoughness() material.pbrMetallicRoughness.baseColorFactor = [1.0, 0.0, 0.0, 1.0] # Red material.pbrMetallicRoughness.metallicFactor = 1.0 material.pbrMetallicRoughness.roughnessFactor = 0.2 material.alphaMode = OPAQUE material.doubleSided = False gltf.materials.append(material) material_index = len(gltf.materials) - 1 # Assign material to a primitive gltf.meshes[0].primitives[0].material = material_index ``` -------------------------------- ### Converting buffer formats Source: https://context7.com/avaturn/pygltflib/llms.txt Demonstrates converting buffer data between data URIs, binary blobs, and external .bin files. ```python from pygltflib import GLTF2, BufferFormat # Load a GLTF with external .bin files gltf = GLTF2().load("model.gltf") # Convert to data URI (base64 embedded in JSON) gltf.convert_buffers(BufferFormat.DATAURI) gltf.save("model_embedded.gltf") # Single self-contained file # Convert to binary blob (for GLB format) gltf.convert_buffers(BufferFormat.BINARYBLOB) gltf.save("model.glb") # Binary GLB file # Convert to external bin files gltf.convert_buffers(BufferFormat.BINFILE) gltf.save("model_external.gltf") # Creates model_external.gltf + 0.bin, 1.bin, etc. # Specify custom path for bin files gltf.convert_buffers(BufferFormat.BINFILE, path="/output/buffers/") # Access binary blob directly blob = gltf.binary_blob() # Returns bytes or None if blob: print(f"Binary blob size: {len(blob)} bytes") ``` -------------------------------- ### Utilize Helper Functions Source: https://context7.com/avaturn/pygltflib/llms.txt Perform common operations such as adding scenes, cameras, nodes, and geometry using the utils module. ```python from pygltflib import GLTF2, Node, Scene from pygltflib.utils import ( find_node_index_by_name, add_node, add_default_scene, add_default_camera, add_indexed_geometry, get_accessor_for_bufferview ) gltf = GLTF2() # Add a default scene add_default_scene(gltf) print(f"Scene: {gltf.scenes[0].name}") # "Scene" # Add a default camera add_default_camera(gltf) print(f"Cameras: {len(gltf.cameras)}") # Add a node to the current scene node = Node() node.name = "MyNode" add_node(gltf, node) print(f"Nodes: {len(gltf.nodes)}") # Find node by name index = find_node_index_by_name(gltf, "MyNode") print(f"Found node at index: {index}") # Add indexed geometry (triangle) indices = [(0, 1, 2)] vertices = [(0.0, 0.0, 0.0), (1.0, 0.0, 0.0), (0.0, 1.0, 0.0)] add_indexed_geometry(gltf, indices, vertices) # Get accessor for a buffer view accessor = get_accessor_for_bufferview(gltf, bufferview=0) if accessor: print(f"Accessor type: {accessor.type}") gltf.save("scene_with_utilities.gltf") ``` -------------------------------- ### Create a simple mesh Source: https://github.com/avaturn/pygltflib/blob/master/README.md Constructs a basic glTF scene containing a primitive triangle with indexed geometry. ```python from pygltflib import * # create gltf objects for a scene with a primitive triangle with indexed geometry gltf = GLTF2() scene = Scene() mesh = Mesh() primitive = Primitive() node = Node() buffer = Buffer() bufferView1 = BufferView() bufferView2 = BufferView() accessor1 = Accessor() accessor2 = Accessor() # add data buffer.uri = "data:application/octet-stream;base64,AAABAAIAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAA=" buffer.byteLength = 44 bufferView1.buffer = 0 bufferView1.byteOffset = 0 bufferView1.byteLength = 6 bufferView1.target = ELEMENT_ARRAY_BUFFER bufferView2.buffer = 0 bufferView2.byteOffset = 8 bufferView2.byteLength = 36 bufferView2.target = ARRAY_BUFFER accessor1.bufferView = 0 accessor1.byteOffset = 0 accessor1.componentType = UNSIGNED_SHORT accessor1.count = 3 accessor1.type = SCALAR accessor1.max = [2] accessor1.min = [0] accessor2.bufferView = 1 accessor2.byteOffset = 0 accessor2.componentType = FLOAT accessor2.count = 3 accessor2.type = VEC3 accessor2.max = [1.0, 1.0, 0.0] accessor2.min = [0.0, 0.0, 0.0] primitive.attributes.POSITION = 1 node.mesh = 0 scene.nodes = [0] # assemble into a gltf structure gltf.scenes.append(scene) gltf.meshes.append(mesh) gltf.meshes[0].primitives.append(primitive) gltf.nodes.append(node) gltf.buffers.append(buffer) gltf.bufferViews.append(bufferView1) gltf.bufferViews.append(bufferView2) gltf.accessors.append(accessor1) gltf.accessors.append(accessor2) # save to file gltf.save("triangle.gltf") ``` -------------------------------- ### Create GLTF2 Object Programmatically Source: https://context7.com/avaturn/pygltflib/llms.txt Illustrates building a glTF 2.0 scene from scratch using Python dataclasses. This includes defining meshes, primitives, nodes, buffers, and accessors for indexed geometry. ```python from pygltflib import ( GLTF2, Scene, Node, Mesh, Primitive, Attributes, Buffer, BufferView, Accessor, UNSIGNED_SHORT, FLOAT, SCALAR, VEC3, ELEMENT_ARRAY_BUFFER, ARRAY_BUFFER ) # Create a triangle mesh with indexed geometry gltf = GLTF2() scene = Scene() mesh = Mesh() primitive = Primitive() node = Node() buffer = Buffer() bufferView1 = BufferView() # For indices bufferView2 = BufferView() # For vertices accessor1 = Accessor() # Index accessor accessor2 = Accessor() # Position accessor # Buffer contains base64-encoded vertex and index data # Format: 3 indices (6 bytes) + padding (2 bytes) + 3 vertices (36 bytes) = 44 bytes buffer.uri = "data:application/octet-stream;base64,AAABAAIAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAA=" buffer.byteLength = 44 # Index buffer view (6 bytes for 3 unsigned shorts) bufferView1.buffer = 0 bufferView1.byteOffset = 0 bufferView1.byteLength = 6 bufferView1.target = ELEMENT_ARRAY_BUFFER # Vertex buffer view (36 bytes for 3 vec3 floats) bufferView2.buffer = 0 bufferView2.byteOffset = 8 bufferView2.byteLength = 36 bufferView2.target = ARRAY_BUFFER # Index accessor accessor1.bufferView = 0 accessor1.byteOffset = 0 accessor1.componentType = UNSIGNED_SHORT accessor1.count = 3 accessor1.type = SCALAR accessor1.max = [2] accessor1.min = [0] # Position accessor accessor2.bufferView = 1 accessor2.byteOffset = 0 accessor2.componentType = FLOAT accessor2.count = 3 accessor2.type = VEC3 accessor2.max = [1.0, 1.0, 0.0] accessor2.min = [0.0, 0.0, 0.0] # Link primitive to accessors primitive.attributes.POSITION = 1 primitive.indices = 0 node.mesh = 0 scene.nodes = [0] # Assemble the glTF structure gltf.scenes.append(scene) gltf.meshes.append(mesh) gltf.meshes[0].primitives.append(primitive) gltf.nodes.append(node) gltf.buffers.append(buffer) gltf.bufferViews.append(bufferView1) gltf.bufferViews.append(bufferView2) gltf.accessors.append(accessor1) gltf.accessors.append(accessor2) # Save the result gltf.save("triangle.gltf") ``` -------------------------------- ### Load a binary file with an unusual extension Source: https://github.com/avaturn/pygltflib/blob/master/README.md Use the `load_binary` helper method to load binary GLTF files that do not have a standard extension. ```python glb = GLTF2().load_binary("BinaryGLTF.glk") # load_json and load_binary helper methods ``` -------------------------------- ### Loading textured models Source: https://context7.com/avaturn/pygltflib/llms.txt Initializes a GLTF2 object from a textured model file. ```python from pygltflib import GLTF2, Image from pygltflib.utils import ImageFormat # Load a GLTF with texture images gltf = GLTF2().load("textured_model.gltf") ``` -------------------------------- ### Run pygltflib Unit Tests Source: https://github.com/avaturn/pygltflib/blob/master/README.md Execute the unit tests for pygltflib using pytest. Ensure the glTF Sample Models repository is cloned in the same directory. ```bash pytest test_pygltflib.py ``` -------------------------------- ### Load a binary GLB file Source: https://github.com/avaturn/pygltflib/blob/master/README.md Load a binary GLB file. The load method automatically detects the binary format based on the file extension. ```python glb_filename = "glTF-Sample-Models/2.0/Box/glTF-Binary/Box.glb" glb = GLTF2().load(glb_filename) # load method auto detects based on extension ``` -------------------------------- ### Add a textured material Source: https://context7.com/avaturn/pygltflib/llms.txt Demonstrates how to append a sampler, image, and texture to a glTF object and link them to a material's base color texture. ```python sampler = Sampler() gltf.samplers.append(sampler) image = Image() image.uri = "albedo.png" gltf.images.append(image) texture = Texture() texture.sampler = len(gltf.samplers) - 1 texture.source = len(gltf.images) - 1 gltf.textures.append(texture) material.pbrMetallicRoughness.baseColorTexture = TextureInfo() material.pbrMetallicRoughness.baseColorTexture.index = len(gltf.textures) - 1 ``` -------------------------------- ### Convert buffers to binary files Source: https://github.com/avaturn/pygltflib/blob/master/README.md Converts internal buffers to external .bin files and saves the GLTF structure. ```python gltf.convert_buffers(BufferFormat.BINFILE) # convert buffers to files gltf.save("test.gltf") # all the buffers are saved in 0.bin, 1.bin, 2.bin. ``` -------------------------------- ### Clone source repository Source: https://github.com/avaturn/pygltflib/blob/master/README.md Command to clone the pygltflib repository from GitLab. ```bash git clone https://gitlab.com/dodgyville/pygltflib ``` -------------------------------- ### Clone glTF Sample Models Repository Source: https://github.com/avaturn/pygltflib/blob/master/README.md Clone the official glTF Sample Models repository to use for testing pygltflib. ```bash git clone https://github.com/KhronosGroup/glTF-Sample-Models ``` -------------------------------- ### Load a GLTF file Source: https://github.com/avaturn/pygltflib/blob/master/README.md Load a GLTF file from the specified path. The library automatically detects the file type. ```python filename = "glTF-Sample-Models/2.0/AnimatedCube/glTF/AnimatedCube.gltf" gltf = GLTF2().load(filename) ``` -------------------------------- ### Convert File Formats Source: https://context7.com/avaturn/pygltflib/llms.txt Utilities for converting between GLB and glTF formats using convenience functions or programmatic saving. ```python from pygltflib.utils import glb2gltf, gltf2glb # Convert GLB to GLTF (creates model.gltf + model.bin) glb2gltf("model.glb") # Convert GLB to GLTF with custom destination glb2gltf("model.glb", destination="output/model.gltf", override=True) # Convert GLTF to GLB gltf2glb("model.gltf") # Convert GLTF to GLB with custom destination gltf2glb("model.gltf", destination="output/model.glb", override=True) ``` ```python from pygltflib import GLTF2 # GLB to GLTF glb = GLTF2().load("model.glb") glb.save("model.gltf") # GLTF to GLB gltf = GLTF2().load("model.gltf") gltf.save("model.glb") ``` -------------------------------- ### Create an image file from GLTF data URIs Source: https://github.com/avaturn/pygltflib/blob/master/README.md Extracts an image from a data URI and saves it as a file on the local filesystem. ```python from pathlib import Path from pygltflib.utils import ImageFormat, Image gltf = GLTF2() image = Image() image.uri = "data:image/png;base64,iVBORw0KGg..." image.name = "myfile.png" # optional file name, if not provided, the image files will be called "0.png", "1.png" gltf.images.append(image) gltf.convert_images(ImageFormat.FILE) # image file will be imported into the GLTF gltf.images[0].uri # will be myfile.png assert Path("myfile.png").exists() is True ``` -------------------------------- ### Remove buffer views Source: https://context7.com/avaturn/pygltflib/llms.txt Demonstrates removing a buffer view and automatically updating references in accessors and images. ```python from pygltflib import GLTF2 gltf = GLTF2().load("model.glb") print(f"Buffer views before: {len(gltf.bufferViews)}") print(f"Buffer size before: {gltf.buffers[0].byteLength}") # Remove a buffer view by index # This updates all accessor and image references removed_view = gltf.remove_bufferView(0) print(f"Removed bufferView with {removed_view.byteLength} bytes") print(f"Buffer views after: {len(gltf.bufferViews)}") print(f"Buffer size after: {gltf.buffers[0].byteLength}") ``` -------------------------------- ### Access glTF extensions Source: https://context7.com/avaturn/pygltflib/llms.txt Shows how to inspect and modify glTF extensions stored as dictionaries within components. ```python from pygltflib import GLTF2 gltf = GLTF2().load("model_with_extensions.gltf") # Check which extensions are used print(f"Extensions used: {gltf.extensionsUsed}") print(f"Extensions required: {gltf.extensionsRequired}") # Access extension data on a primitive (e.g., Draco compression) primitive = gltf.meshes[0].primitives[0] if "KHR_draco_mesh_compression" in primitive.extensions: draco = primitive.extensions["KHR_draco_mesh_compression"] print(f"Draco bufferView: {draco['bufferView']}") print(f"Draco attributes: {draco['attributes']}") # Access extension data on a material material = gltf.materials[0] if "KHR_materials_transmission" in material.extensions: transmission = material.extensions["KHR_materials_transmission"] print(f"Transmission factor: {transmission['transmissionFactor']}") # Add custom extension data material.extensions["KHR_materials_unlit"] = {} gltf.extensionsUsed.append("KHR_materials_unlit") # Access top-level extensions if gltf.extensions: print(f"Root extensions: {gltf.extensions}") # Extras field for custom application data gltf.extras["customData"] = {"exportedBy": "myApp", "version": "1.0"} ``` -------------------------------- ### Create GLTF2 object from arrays Source: https://github.com/avaturn/pygltflib/blob/master/README.md Construct a GLTF2 object by mapping binary blobs to accessors and buffer views. ```python triangles_binary_blob = triangles.flatten().tobytes() points_binary_blob = points.tobytes() gltf = pygltflib.GLTF2( scene=0, scenes=[pygltflib.Scene(nodes=[0])], nodes=[pygltflib.Node(mesh=0)], meshes=[ pygltflib.Mesh( primitives=[ pygltflib.Primitive( attributes=pygltflib.Attributes(POSITION=1), indices=0 ) ] ) ], accessors=[ pygltflib.Accessor( bufferView=0, componentType=pygltflib.UNSIGNED_BYTE, count=triangles.size, type=pygltflib.SCALAR, max=[int(triangles.max())], min=[int(triangles.min())], ), pygltflib.Accessor( bufferView=1, componentType=pygltflib.FLOAT, count=len(points), type=pygltflib.VEC3, max=points.max(axis=0).tolist(), min=points.min(axis=0).tolist(), ), ], bufferViews=[ pygltflib.BufferView( buffer=0, byteLength=len(triangles_binary_blob), target=pygltflib.ELEMENT_ARRAY_BUFFER, ), pygltflib.BufferView( buffer=0, byteOffset=len(triangles_binary_blob), byteLength=len(points_binary_blob), target=pygltflib.ARRAY_BUFFER, ), ], buffers=[ pygltflib.Buffer( byteLength=len(triangles_binary_blob) + len(points_binary_blob) ) ], ) gltf.set_binary_blob(triangles_binary_blob + points_binary_blob) ``` -------------------------------- ### Add a scene to a GLTF2 object Source: https://github.com/avaturn/pygltflib/blob/master/README.md Create a Scene object and append it to the GLTF2 object's scenes list. The first scene added will be the default scene. ```python from pygltflib import GLTF2, Scene gltf = GLTF2() scene = Scene() gltf.scenes.append(scene) # scene available at gltf.scenes[0] ``` -------------------------------- ### Creating meshes with numpy and binary blobs Source: https://context7.com/avaturn/pygltflib/llms.txt Uses numpy arrays to define geometry and sets them as a binary blob on the GLTF2 object for efficient mesh creation. ```python import numpy as np import pygltflib # Define mesh geometry with numpy points = np.array([ [-0.5, -0.5, 0.5], [0.5, -0.5, 0.5], [-0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [0.5, -0.5, -0.5], [-0.5, -0.5, -0.5], [0.5, 0.5, -0.5], [-0.5, 0.5, -0.5], ], dtype="float32") triangles = np.array([ [0, 1, 2], [3, 2, 1], [1, 0, 4], [5, 4, 0], [3, 1, 6], [4, 6, 1], [2, 3, 7], [6, 7, 3], [0, 2, 5], [7, 5, 2], [5, 7, 4], [6, 4, 7], ], dtype="uint8") # Convert to binary blobs triangles_blob = triangles.flatten().tobytes() points_blob = points.tobytes() # Create complete glTF structure gltf = pygltflib.GLTF2( scene=0, scenes=[pygltflib.Scene(nodes=[0])], nodes=[pygltflib.Node(mesh=0)], meshes=[ pygltflib.Mesh(primitives=[ pygltflib.Primitive( attributes=pygltflib.Attributes(POSITION=1), indices=0 ) ]) ], accessors=[ pygltflib.Accessor( bufferView=0, componentType=pygltflib.UNSIGNED_BYTE, count=triangles.size, type=pygltflib.SCALAR, max=[int(triangles.max())], min=[int(triangles.min())], ), pygltflib.Accessor( bufferView=1, componentType=pygltflib.FLOAT, count=len(points), type=pygltflib.VEC3, max=points.max(axis=0).tolist(), min=points.min(axis=0).tolist(), ), ], bufferViews=[ pygltflib.BufferView( buffer=0, byteLength=len(triangles_blob), target=pygltflib.ELEMENT_ARRAY_BUFFER, ), pygltflib.BufferView( buffer=0, byteOffset=len(triangles_blob), byteLength=len(points_blob), target=pygltflib.ARRAY_BUFFER, ), ], buffers=[ pygltflib.Buffer(byteLength=len(triangles_blob) + len(points_blob)) ], ) # Set the binary blob gltf.set_binary_blob(triangles_blob + points_blob) # Save as GLB gltf.save("cube.glb") # Or save to bytes for streaming glb_bytes = b"".join(gltf.save_to_bytes()) ``` -------------------------------- ### Import PNG files as textures Source: https://github.com/avaturn/pygltflib/blob/master/README.md Adds an external image file to the GLTF and converts it to a data URI. ```python from pygltflib import GLTF2 from pygltflib.utils import ImageFormat, Image gltf = GLTF2() image = Image() image.uri = "myfile.png" gltf.images.append(image) gltf.convert_images(ImageFormat.DATAURI) gltf.images[0].uri # will now be something like "data:image/png;base64,iVBORw0KGg..." gltf.images[0].name # will be myfile.png ``` -------------------------------- ### Convert texture images with custom filenames Source: https://github.com/avaturn/pygltflib/blob/master/README.md Sets a custom filename for an image before converting it to an external file. ```python from pygltflib import GLTF2 from pygltflib.utils import ImageFormat filename = "glTF-Sample-Models/2.0/AnimatedCube/glTF/AnimatedCube.gltf" gltf = GLTF2().load(filename) gltf.images[0].name = "cube.png" # will save the data uri to this file (regardless of data format) gltf.convert_images(ImageFormat.FILE) gltf.images[0].uri # will now be cube.png and the texture image will be saved in cube.png ``` -------------------------------- ### Save and load GLTF2 bytes Source: https://github.com/avaturn/pygltflib/blob/master/README.md Convert the glTF object to a binary glb format and load it back. ```python glb = b"".join(gltf.save_to_bytes()) ``` ```python gltf = pygltflib.GLTF2.load_from_bytes(glb) ``` -------------------------------- ### Specify image conversion path Source: https://github.com/avaturn/pygltflib/blob/master/README.md Overrides the default directory for saving converted image files. ```python from pygltflib import GLTF2 from pygltflib.utils import ImageFormat filename = "glTF-Sample-Models/2.0/AnimatedCube/glTF/AnimatedCube.gltf" gltf = GLTF2().load(filename) gltf.images[0].name = "cube.png" # will save the data uri to this file (regardless of data format) gltf.convert_images(ImageFormat.FILE, path='/destination/') gltf.images[0].uri # will now be cube.png and the texture image will be saved in /destination/cube.png ``` -------------------------------- ### Convert Between GLTF and GLB Source: https://github.com/avaturn/pygltflib/blob/master/README.md Methods for converting between GLTF and GLB formats. ```python from pygltflib import GLTF2 # convert glb to gltf glb = GLTF2().load("glTF-Sample-Models/2.0/Box/glTF-Binary/Box.glb") glb.save("test.gltf") # convert gltf to glb gltf = GLTF2().load("glTF-Sample-Models/2.0/Box/glTF/Box.gltf") gltf.save("test.glb") ``` ```python from pygltflib import GLTF2 from pygltflib.utils import glb2gltf, gltf2glb # convert glb to gltf glb2gltf("glTF-Sample-Models/2.0/Box/glTF-Binary/Box.glb") # convert gltf to glb gltf2glb("glTF-Sample-Models/2.0/Box/glTF/Box.gltf", "test.glb", override=True) ``` -------------------------------- ### Import pygltflib and numpy Source: https://github.com/avaturn/pygltflib/blob/master/README.md Required imports for working with glTF structures and numerical data. ```python import numpy as np import pygltflib ``` -------------------------------- ### Convert Buffers Source: https://github.com/avaturn/pygltflib/blob/master/README.md Utility for converting buffer storage formats within a GLTF2 file. ```python from pygltflib import GLTF2, BufferFormat gltf = GLTF2().load("glTF-Sample-Models/2.0/Box/glTF/Box.gltf") gltf.convert_buffers(BufferFormat.DATAURI) # convert buffer URIs to data. gltf.save_binary("test.glb") # try and save, will get warning. # Will receive: Warning: Unable to save data uri to glb format. gltf.convert_buffers(BufferFormat.BINARYBLOB) # convert buffers to GLB blob gltf.save_binary("test.glb") gltf.convert_buffers(BufferFormat.BINFILE) # convert buffers to files gltf.save("test.gltf") # all the buffers are saved in 0.bin, 1.bin, 2.bin. ``` -------------------------------- ### Import and Export Images Source: https://context7.com/avaturn/pygltflib/llms.txt Techniques for appending new images to a glTF object and exporting embedded data URIs to external files. ```python gltf = GLTF2() image = Image() image.uri = "texture.png" image.name = "my_texture" gltf.images.append(image) gltf.convert_images(ImageFormat.DATAURI) # Embeds the image ``` ```python gltf = GLTF2().load("model.glb") gltf.export_datauri_as_image_file( gltf.images[0].uri, name="exported_texture.png", destination="/output/", override=True, index=0 ) ``` -------------------------------- ### Convert GLB to GLTF Source: https://github.com/avaturn/pygltflib/blob/master/README.md Converts a binary GLB file into a standard GLTF file format. ```python from pygltflib.utils import glb2gltf, gltf2glb # convert glb to gltf glb2gltf("glTF-Sample-Models/2.0/Box/glTF-Binary/Box.glb") ``` -------------------------------- ### Access the first node of a scene Source: https://github.com/avaturn/pygltflib/blob/master/README.md Load a GLTF file, access the current scene using the `gltf.scene` index, and then retrieve the first node from the scene's nodes list. Note that `scene.nodes` contains indices, not the node objects themselves. ```python gltf = GLTF2().load("glTF-Sample-Models/2.0/Box/glTF/Box.gltf") current_scene = gltf.scenes[gltf.scene] node_index = current_scene.nodes[0] # scene.nodes is the indices, not the objects box = gltf.nodes[node_index] box.matrix # will output vertices for the box object ``` -------------------------------- ### Access GLTF extensions Source: https://github.com/avaturn/pygltflib/blob/master/README.md Accesses specific extensions defined on primitives or materials. ```python # on a primitve gltf.meshes[0].primitives[0].extensions['KHR_draco_mesh_compression'] # on a material gltf.materials[0].extensions['ADOBE_materials_thin_transparency'] ``` -------------------------------- ### Access Mesh Data with Numpy Source: https://context7.com/avaturn/pygltflib/llms.txt Shows how to load a glTF model and access its mesh data, preparing it for manipulation with libraries like numpy. This snippet focuses on retrieving the data pointers. ```python import struct import numpy as np from pygltflib import GLTF2 # Load a model gltf = GLTF2().load("Box.gltf") # Get the first mesh's first primitive mesh = gltf.meshes[0] primitive = mesh.primitives[0] ``` -------------------------------- ### Read vertex data from a primitive Source: https://github.com/avaturn/pygltflib/blob/master/README.md Loads a glTF file and accesses the first mesh in the scene. ```python import pathlib import struct import miniball import numpy from pygltflib import GLTF2 # load an example gltf file from the khronos collection fname = pathlib.Path("glTF-Sample-Models/2.0/Box/glTF-Embedded/Box.gltf") gltf = GLTF2().load(fname) # get the first mesh in the current scene (in this example there is only one scene and one mesh) mesh = gltf.meshes[gltf.scenes[gltf.scene].nodes[0]] ``` -------------------------------- ### Convert texture images to PNG files Source: https://github.com/avaturn/pygltflib/blob/master/README.md Converts embedded texture images into external PNG files. ```python from pygltflib import GLTF2 from pygltflib.utils import ImageFormat filename = "glTF-Sample-Models/2.0/AnimatedCube/glTF/AnimatedCube.gltf" gltf = GLTF2().load(filename) gltf.convert_images(ImageFormat.FILE) gltf.images[0].uri # will now be 0.png and the texture image will be saved in 0.png ``` -------------------------------- ### Convert buffers to GLB binary buffers Source: https://github.com/avaturn/pygltflib/blob/master/README.md Convert all buffers within a GLTF object to the binary blob format suitable for GLB files. This is useful when preparing a GLTF object for export as a single binary file. ```python from pygltflib import GLTF2, BufferFormat gltf = GLTF2().load("glTF-Sample-Models/2.0/Box/glTF/Box.gltf") gltf.convert_buffers(BufferFormat.BINARYBLOB) # convert buffers to GLB blob ``` -------------------------------- ### Convert glTF Images Source: https://context7.com/avaturn/pygltflib/llms.txt Methods for converting image storage formats within a glTF object, including data URIs, external files, and buffer views. ```python gltf.convert_images(ImageFormat.DATAURI) print(f"Image URI: {gltf.images[0].uri[:50]}...") # data:image/png;base64,... ``` ```python gltf.convert_images(ImageFormat.FILE) print(f"Image file: {gltf.images[0].uri}") # 0.png ``` ```python gltf.convert_images(ImageFormat.FILE, path="/output/textures/") ``` ```python gltf.convert_images(ImageFormat.BUFFERVIEW) print(f"Image bufferView: {gltf.images[0].bufferView}") ``` -------------------------------- ### Extract Vertices from Mesh Primitive Source: https://github.com/avaturn/pygltflib/blob/master/README.md Iterates through mesh primitives, retrieves binary vertex data from buffers, and unpacks it into Python floats. Requires 'gltf', 'struct', and 'numpy'. ```python import struct import numpy import miniball # Assuming 'gltf' is a loaded pygltflib object # Assuming 'mesh' is a mesh object from the gltf file # get the vertices for each primitive in the mesh (in this example there is only one) for primitive in mesh.primitives: # get the binary data for this mesh primitive from the buffer accessor = gltf.accessors[primitive.attributes.POSITION] bufferView = gltf.bufferViews[accessor.bufferView] buffer = gltf.buffers[bufferView.buffer] data = gltf.get_data_from_buffer_uri(buffer.uri) # pull each vertex from the binary buffer and convert it into a tuple of python floats vertices = [] for i in range(accessor.count): index = bufferView.byteOffset + accessor.byteOffset + i*12 # the location in the buffer of this vertex d = data[index:index+12] # the vertex data v = struct.unpack("