GLTFDocument in Godot – Complete Guide

Welcome to our comprehensive guide on using the GLTFDocument class in Godot 4, the powerful and versatile game development framework. GLTFDocument is at the forefront of 3D asset workflows in Godot, and understanding its capabilities is crucial for anyone looking to enhance their game projects with rich, detailed environments and characters.

By diving into this tutorial, you’ll gain the knowledge you need to confidently manipulate GLTF files within your Godot projects, whether you’re a beginner just starting out or an experienced coder looking to refine your skills.

What is GLTFDocument?

GLTFDocument is a class in Godot 4 that serves as a gateway to the glTF 2.0 (GL Transmission Format) ecosystem. It provides methods for importing, manipulating, and exporting 3D assets in the glTF format, a royalty-free specification for the efficient transmission and loading of 3D scenes and models by applications.

What is GLTFDocument Used For?

The GLTFDocument class performs a variety of functions, allowing you to:

  • Import 3D assets from GLTF files into your Godot scenes.
  • Export Godot scenes as GLTF files for use in other applications or engines.
  • Dynamically generate and manipulate 3D assets at runtime.
  • Extend its functionality via custom extensions.

Why Should I Learn GLTFDocument?

Mastering the GLTFDocument class is beneficial for a number of reasons:

  • Interoperability: glTF is known as the “JPEG of 3D” and is widely supported, making your Godot assets portable and versatile.
  • Efficiency: Using GLTFDocument functions can optimize the performance of your game by simplifying asset management.
  • Customization: GLTFDocument’s extensible nature allows for the creation of advanced features, tailored to your project’s needs.

Ready to get started? Let’s dive into the world of GLTFDocument and unlock the potential of 3D asset management in Godot 4!

CTA Small Image
FREE COURSES AT ZENVA
LEARN GAME DEVELOPMENT, PYTHON AND MORE
ACCESS FOR FREE
AVAILABLE FOR A LIMITED TIME ONLY

Importing 3D Assets with GLTFDocument

To start importing 3D assets, you’ll first need to initialize a GLTFDocument instance. Here’s how to do that in GDScript:

var gltf_document = GLTFDocument.new()

Once you have your GLTFDocument instance, you can load a glTF file using the load function:

var gltf_file_path = "res://path_to_your_file.gltf"
var error_code = gltf_document.load(gltf_file_path)
if error_code == OK:
    print("GLTF file loaded successfully.")
else:
    print("Failed to load GLTF file with error code: ", error_code)

After loading the glTF file, you can import the scene with the following code:

var imported_scene = gltf_document.import_scene(gltf_file_path, 0)
add_child(imported_scene)

Manipulating and Exporting 3D Nodes

You can not only import but also manipulate the scene nodes before you export them. This can be helpful if you wish to apply transformations or edit properties programmatically. To do this, load the nodes first:

var nodes = gltf_document.get_nodes()

Let’s say you want to rotate a specific node; you’d access the node by its index and apply a rotation:

var node_index = 1 # Index of the node you want to modify (this would be specific to your scene structure)
var node = nodes[node_index]
node.rotate(Vector3(0, 1, 0), PI / 2) # Rotate node 90 degrees around the Y-axis

To export a node or an entire scene to a GLTF file, specify the file path where you want to save it, and use the save_scene function:

var export_file_path = "res://path_to_export_file.gltf"
var export_error = gltf_document.save_scene(export_file_path)
if export_error == OK:
    print("Scene exported successfully.")
else:
    print("Failed to export scene with error code: ", export_error)

Adding and Removing Nodes

If you want to add a new node to the scene programmatically, you’d create the node and then add it to the GLTFDocument’s nodes array. Here’s how to add a Spatial node:

var new_node = Spatial.new()
new_node.name = "My New Node"
gltf_document.get_nodes().append(new_node)

Removing a node is just as straightforward. You can remove a node by its index:

var node_to_remove_index = 2 # Index of the node you want to remove
gltf_document.get_nodes().remove(node_to_remove_index)

Using Custom Extensions

GLTFDocument class also allows the use of custom extensions. Let’s define a new custom extension:

var custom_extension_name = "MY_CUSTOM_EXTENSION"
var custom_extension_data = {"custom_property": "custom_value"}
gltf_document.add_extension(custom_extension_name, custom_extension_data)

To retrieve the data from your custom extension:

var retrieved_extension_data = gltf_document.get_extension(custom_extension_name)
if retrieved_extension_data:
    print("Custom extension data: ", retrieved_extension_data)

Armed with these basics, you’re now equipped to begin working with 3D assets in your Godot projects using the GLTFDocument class. Remember that these are foundational concepts – as you grow more comfortable, you’ll discover even more powerful ways to use GLTFDocument for your specific use cases.

As you delve deeper into GLTFDocument’s functionalities, you’ll start to see the power of procedural content generation and asset manipulation. Here are some further examples of what you can accomplish with this Godot 4 class:

Setting up animation players for imported animations is a common requirement. Once you’ve imported your scene, you’ll want to make sure that all animations are imported as well:

var animations = gltf_document.import_animations(gltf_file_path)
for animation in animations:
    var anim_player = AnimationPlayer.new()
    anim_player.add_animation(animation.name, animation)
    imported_scene.add_child(anim_player)
    anim_player.play(animation.name)

You might also want to dynamically change textures on imported models. This can be done by first acquiring the material and then changing its texture:

var mesh_instance = imported_scene.get_node("MeshInstancePath")
var surface_material = mesh_instance.get_surface_material(0)

if surface_material is SpatialMaterial:
    var new_texture = preload("res://path_to_new_texture.png")
    surface_material.albedo_texture = new_texture

Customizing the shader parameters can significantly change how the model looks. Assuming the material uses a ShaderMaterial, you can modify shader parameters like this:

var shader_material = surface_material as ShaderMaterial
shader_material.set_shader_param("param_name", value)

In a complex scene, you may want to find all instances of a particular type of node, such as all lights or cameras, and modify their properties or even replace them:

var all_lights = imported_scene.get_children_by_type("Light")
for light in all_lights:
    light.energy = 2.0 # Brighten all the lights

Sometimes you might need to optimize your scene by merging meshes with the same materials. This can help in reducing draw calls:

gltf_document.merge_meshes_by_material()

Lastly, if you’re creating a level editor or a tool within Godot, you might want to offer the ability to create glTF scenes from scratch. Here’s how to create an empty GLTFDocument and add a node to it:

var new_gltf_document = GLTFDocument.new()
var root_node = Spatial.new()
root_node.name = "RootNode"
new_gltf_document.get_nodes().append(root_node)
# Don't forget to save your newly created GLTFDocument!
new_gltf_document.save_scene("res://new_scene.gltf")

The examples provided offer a glimpse into the diverse capabilities of the GLTFDocument class. Whether you’re automating repetitive tasks, customizing assets on the fly, or building complex procedural scenes, GLTFDocument gives you the tools you need to elevate your Godot game projects with ease. Keep experimenting, and see how GLTFDocument can fit into your asset workflow.

Fine-tuning imported 3D scenes often involves dealing with materials. You might want to replace all instances of a specific material with another:

var old_material = preload("res://path_to_old_material.tres")
var new_material = preload("res://path_to_new_material.tres")

for i in range(gltf_document.get_nodes().size()):
    var node = gltf_document.get_nodes()[i]
    if node is MeshInstance:
        for j in range(node.get_surface_material_count()):
            if node.get_surface_material(j) == old_material:
                node.set_surface_material(j, new_material)

If you’re looking to create dynamic scenes, you may also want to instance scenes or nodes at specific points in your 3D model. This can be done by identifying bone attachments or dummy objects:

var item_scene = preload("res://path_to_item_scene.tscn")
var attachment_point_name = "SpawnPoint"

for i in range(gltf_document.get_nodes().size()):
    var node = gltf_document.get_nodes()[i]
    if node.name == attachment_point_name:
        var instanced_scene = item_scene.instance()
        node.add_child(instanced_scene)

Animations can breathe life into your models, but sometimes you need to edit them programmatically. Here’s how you might alter the playback speed of an animation:

var anim_speed = 1.5
var anim_name = "WalkCycle"
var anim_player = imported_scene.find_node("AnimationPlayer", true, false)

if anim_player and anim_player.has_animation(anim_name):
    var anim = anim_player.get_animation(anim_name)
    anim_player.play(anim_name)
    anim_player.set_playback_speed(anim_speed)

Now, consider a case where you’d like to automate LOD (Level of Detail) generation by scaling down a high-poly mesh model:

var lod_factor = 0.5
var high_poly_mesh_path = "res://path_to_high_poly_mesh.instance"

var high_poly_mesh_node = imported_scene.get_node(high_poly_mesh_path)
if high_poly_mesh_node and high_poly_mesh_node is MeshInstance:
    var mesh = high_poly_mesh_node.mesh
    if mesh and mesh is ArrayMesh:
        var new_lod_mesh = mesh.duplicate()
        new_lod_mesh.surface_set_material(0, high_poly_mesh_node.get_surface_material(0))
        new_lod_mesh.lightmap_scale *= lod_factor
        high_poly_mesh_node.mesh = new_lod_mesh

Organizing your scene hierarchies is key for readability and efficient scene management. Here’s how you could reparent a node to a new parent within your scene:

var node_path = "res://path_to_node"
var new_parent_path = "res://path_to_new_parent"

var node_to_reparent = imported_scene.get_node(node_path)
var new_parent_node = imported_scene.get_node(new_parent_path)

if node_to_reparent and new_parent_node:
    node_to_reparent.get_parent().remove_child(node_to_reparent)
    new_parent_node.add_child(node_to_reparent)
    node_to_reparent.owner = imported_scene # Ensure proper ownership for saving

When exporting scenes, it’s often important to include external resources like textures. Use the ‘export_textures’ flag to also export these when saving the scene:

var export_file_path = "res://exported_scene_with_textures.gltf"
gltf_document.export_textures = true
var export_error = gltf_document.save_scene(export_file_path)
if export_error == OK:
    print("Scene with textures exported successfully.")
else:
    print("Failed to export scene with textures.")

These code examples are designed to illustrate the versatility of the GLTFDocument class in Godot 4, showing how it can be used to manipulate and optimize your 3D scenes to better suit the unique needs of your game or application. As always, feel encouraged to tinker with the examples provided here and explore the full range of glTF options available to you in Godot 4.

Continuing Your Godot Journey

Embarking on your 3D game development journey with the Godot engine is an adventure filled with endless possibilities, and mastering tools like GLTFDocument is just the beginning. To keep the momentum going and enhance your skills further, we invite you to explore our Godot Game Development Mini-Degree. This curated selection of courses will guide you through the intricacies of Godot, lifting you from a novice to a confident game developer capable of creating your own cross-platform games.

Whether you yearn to craft compelling 2D platformers, intricate 3D adventures, or anything in between, this Mini-Degree has you covered. With a flexible learning schedule, quality content, and practical projects, you’ll be well-equipped to bring your game ideas to life. And if you’re looking to broaden your knowledge even further, be sure to check out our wider selection of Godot courses.

At Zenva, we’re committed to helping you grow your skills and prepare for an exciting future in game development. Let’s continue turning your passion into a reality with our extensive learning resources and community support. Start your next chapter in game development today!

Conclusion

In the realm of digital creation, the knowledge you’ve gained about GLTFDocument in Godot 4 propels you towards new heights, unlocking the full potential of 3D asset management. With these skills in hand, the pipeline from imagination to screen for your 3D worlds becomes more intuitive, streamlined, and dynamic. Continue to explore, experiment, and engage with each lesson, as every line of code is a step towards your masterpiece.

Ready for your next challenge? Expand your expertise with our Godot Game Development Mini-Degree, where new doors await to be opened, and every course is another puzzle piece to completing your game development knowledge. At Zenva, your journey is our journey, and we’re here with the tools and tutorials that make a real difference. Let’s craft those vibrant game experiences, together. Happy coding, future game developer!

FREE COURSES
Python Blog Image

FINAL DAYS: Unlock coding courses in Unity, Godot, Unreal, Python and more.