o
odinpkg.dev
packages / library / odin_gltf

odin_gltf

25d80a4library

No description provided.

MIT · updated 4 months ago

odin_cgltf

odin_cgltf is an Odin-native glTF 2.0 parser/decoder/validator port of cgltf.

It supports:

  • .gltf JSON containers
  • .glb binary containers (JSON + BIN chunk)
  • typed decode into Odin structs
  • validation of core glTF structural rules
  • cgltf-style extension flags (including defaults that allow all extensions)

What This Library Does

  • Parse file bytes into a Document (parse_file, parse_bytes)
  • Decode typed model data into Decoded_Model (decode_document)
  • Validate model references/ranges/version (validate_gltf, validate_gltf_with_options)
  • Track extensionsUsed and extensionsRequired as bitflags in decode output

What This Library Does Not Do

  • No GPU upload
  • No image decode
  • No Draco mesh decode implementation (the extension payload is parsed and validated structurally)
  • No automatic external resource loading (.bin, textures) into engine memory

Engine Integration Flow

Use this lifecycle in your 3D engine:

  1. Parse source file (.gltf or .glb)
  2. Decode typed model data
  3. Validate model
  4. Resolve buffers/images/material data into your engine asset types
  5. Destroy Decoded_Model and Document once copied into engine-owned structures

Minimal Example

package your_engine

import "core:fmt"
import gltf "path/to/odin_cgltf"

load_gltf_asset :: proc(path: string) -> bool {
	doc, parse_err := gltf.parse_file(path)
	if gltf.has_error(parse_err) {
		fmt.printf("parse failed: %v\n", parse_err.status)
		return false
	}
	defer gltf.destroy_document(&doc)

	decoded, decode_err := gltf.decode_document(&doc)
	if gltf.has_decode_error(decode_err) {
		fmt.printf("decode failed: %v\n", decode_err.status)
		return false
	}
	defer gltf.destroy_decoded_model(&decoded)

	validation_err := gltf.validate_gltf(&doc, &decoded.model)
	if gltf.has_validation_error(validation_err) {
		fmt.printf("validation failed: %v\n", validation_err.status)
		return false
	}

	// Build engine resources from decoded.model + buffer data.
	return true
}

Reading Buffer Data

For each model.buffers[i]:

  • If source is .glb and i == 0 with empty uri, bytes are in doc.bin_chunk.
  • Otherwise load buffers[i].uri from disk relative to the .gltf file directory.

Then resolve each accessor through:

  • accessor.bufferView
  • bufferViews[bufferView].byteOffset
  • accessor.byteOffset
  • accessor.componentType, accessor.type
  • optional bufferViews[...].byteStride

This is where engines build vertex/index streams and mesh primitives.

Extension Policy

Default validation is permissive:

  • all known cgltf extension flags are allowed
  • unknown required extension names are allowed

Use strict policy when needed:

options := gltf.Validation_Options{
	allowed_extension_flags           = gltf.Extension_Flags(
		u32(gltf.CGLTF_EXTENSION_FLAG_MATERIALS_UNLIT) |
		u32(gltf.CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM),
	),
	allow_unknown_required_extensions = false,
}
err := gltf.validate_gltf_with_options(&doc, &decoded.model, options)

Extension bitfields are available on Decoded_Model:

  • used_extension_flags
  • required_extension_flags

Testing

The test suite covers:

  • parser/decode/validation status paths
  • manifest-based corpus runs over:
    • test/glTF-Sample-Assets/Models
    • test/free_models

Run:

odin test .