loadModel for example Robot fails · Issue #358 · raylib-zig/raylib-zig · GitHub
Skip to content

loadModel for example Robot fails #358

Open

Description

@void-ripper

Hi,

i was using the little Robot model from the Raylib examples.
The model is okay.
Loading the modal via C and LoadModel works fine.
Loading the modal via Rust, custom bindings and the Raylib crate works.

But as you guessed by the title, in Zig it just crashes.

// window setup
// ...
 _ = try rl.loadModel("sponge.glb");
 _ = try rl.loadModel("robot.glb"); // returns an error because the file is allegedly not valid
 _ = try rl.loadModelAnimations("robot.glb");  // works fine if loadModel("robot.glb") is commented out
// ...
// mainloop and cleanup

Here the relevant part of the Raylib logs.

INFO: FILEIO: [sponge.glb] File loaded successfully
INFO: MODEL: [sponge.glb] Model basic data (glb) loaded successfully
INFO:     > Meshes count: 1
INFO:     > Materials count: 0 (+1 default)
INFO: VAO: [ID 2] Mesh uploaded successfully to VRAM (GPU)
INFO: FILEIO: [robot.glb] File loaded successfully
INFO: MODEL: [robot.glb] Model basic data (glb) loaded successfully
INFO:     > Meshes count: 14
INFO:     > Materials count: 3 (+1 default)
INFO: VAO: [ID 3] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 4] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 5] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 6] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 7] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 8] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 9] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 10] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 11] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 12] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 13] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 14] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 15] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 16] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 17] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 18] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 19] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 20] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 21] Mesh uploaded successfully to VRAM (GPU)
INFO: TEXTURE: [ID 2] Unloaded texture data from VRAM (GPU)
INFO: SHADER: [ID 3] Default shader unloaded successfully
INFO: TEXTURE: [ID 1] Default texture unloaded successfully
INFO: Window closed successfully
error: LoadModel

The error seems to be thrown, because the model in question is not valid.
This seems odd, because it is the official example model provided by Raylib.
In addition to, the file works flawlessly in every other binding of Raylib.

The difference is in this function.
[raylib.zig:2498]

pub fn loadModel(fileName: [:0]const u8) error{LoadModel}!Model {
    const model = cdef.LoadModel(@as([*c]const u8, @ptrCast(fileName)));
    const isValid = cdef.IsModelValid(model);
    return if (isValid) model else error.LoadModel;
}

So as a test, i used the IsModelValid in the C version.
And it failed, it said the model is not valid.

(As side node, should the model not be "unloaded", if it is not valid, because now an invalid model pollutes the graphics memory with its allocated VAO and VBO, and there is no way to do it for the user since the model is never returned!)

Sooo, in the official examples of Raylib is an unvalid GLTF model file.
Which works flawlessly fine, because nobody ever uses IsModelValid.

raylib-zig failed successfully !

This is not a failure or a bug. Nor is it important.
But i feel this should in some way be communicated.

Activity

  1. Not-Nik commented on Aug 17, 2026

    @Not-Nik
    Member

    Can you check which condition makes IsModelValid fail with a debugger? If a Model is usable, the function shouldn't fail, so chances are good that this is a raylib bug, not an issue with us verifying loading worked.

  2. void-ripper commented on Aug 29, 2026

    @void-ripper
    Author

    After some debugging

    if ((model.meshes[i].boneIndices != NULL) && (model.meshes[i].vboId[7] == 0)) { result = false; break; }

    Thats were it fails. Since me and GDB are not really friends, i was not able to detect which part of the expression was failing.
    But at this point i invested to much time into this.

    I go with my gut feeling, we have boneIndices, but vboId[7] != 0, could be an initialization error.
    But should vboId not be unequal zero, because we have a vbo initialized ?

  3. DanielVernall commented on Sep 27, 2026

    @DanielVernall

    I can reproduce this with the official robot.glb example model using raylib 6.0.

    The model loads successfully through the C API (raylib.cdef), including all 20 VAOs shown in the raylib log:

    INFO: FILEIO: [assets/models/robot.glb] File loaded successfully
    INFO: MODEL: [assets/models/robot.glb] Model basic data (glb) loaded successfully
    INFO:     > Meshes count: 14
    INFO:     > Materials count: 3 (+1 default)
    INFO: VAO: [ID 2] Mesh uploaded successfully to VRAM (GPU)
    ...
    INFO: VAO: [ID 20] Mesh uploaded successfully to VRAM (GPU)
    

    However, calling IsModelValid() immediately afterwards returns:

    valid: false
    

    Inspecting the returned Model gives:

    meshes: 19
    materials: 4
    

    All 19 meshes have non-null boneIndices and boneWeights, but their corresponding bone VBOs are zero. For example:

    mesh 0: boneIndices=u16@..., boneWeights=f32@..., vbo=[6, 0, 7, 0, 0, 0, 8, 0, 0]
    mesh 1: boneIndices=u16@..., boneWeights=f32@..., vbo=[9, 0, 10, 0, 0, 0, 11, 0, 0]
    ...
    mesh 18: boneIndices=u16@..., boneWeights=f32@..., vbo=[60, 0, 61, 0, 0, 0, 62, 0, 0]
    

    This appears relevant because IsModelValid() checks the bone buffers when boneIndices/boneWeights are present. The result is therefore false even though the model has successfully loaded and its regular vertex/index buffers have valid VBO IDs.

    There is also a notable discrepancy in the output:

    raylib loader: 14 meshes, 3 materials (+1 default)
    Model struct: 19 meshes, 4 materials
    

    The code used:

    const model = rl.cdef.LoadModel("assets/models/robot.glb");
    defer rl.cdef.UnloadModel(model);
    
    std.debug.print("valid: {}\n", .{rl.cdef.IsModelValid(model)});
    
    std.debug.print("meshes: {d}\n", .{model.meshCount});
    std.debug.print("materials: {d}\n", .{model.materialCount});
    std.debug.print("meshMaterial: {*}\n", .{model.meshMaterial});
    
    for (0..@intCast(model.meshCount)) |i| {
        const mesh = model.meshes[i];
    
        std.debug.print(
            "mesh {d}: boneIndices={*}, boneWeights={*}, vbo=[{d}, {d}, {d}, {d}, {d}, {d}, {d}, {d}, {d}]\n",
            .{
                i,
                mesh.boneIndices,
                mesh.boneWeights,
                mesh.vboId[0],
                mesh.vboId[1],
                mesh.vboId[2],
                mesh.vboId[3],
                mesh.vboId[4],
                mesh.vboId[5],
                mesh.vboId[6],
                mesh.vboId[7],
                mesh.vboId[8],
            },
        );
    }

    The full printed output:

    valid: false
    meshes: 19
    materials: 4
    meshMaterial: c_int@1fcba414da0
    mesh 0: boneIndices=u16@1fcba5699f0, boneWeights=f32@1fcba569ea0, vbo=[6, 0, 7, 0, 0, 0, 8, 0, 0]
    mesh 1: boneIndices=u16@1fcb8ade940, boneWeights=f32@1fcba56cd10, vbo=[9, 0, 10, 0, 0, 0, 11, 0, 0]
    mesh 2: boneIndices=u16@1fcb2fbd0f0, boneWeights=f32@1fcba56f9a0, vbo=[12, 0, 13, 0, 0, 0, 14, 0, 0]
    mesh 3: boneIndices=u16@1fcb2fbced0, boneWeights=f32@1fcba570410, vbo=[15, 0, 16, 0, 0, 0, 17, 0, 0]
    mesh 4: boneIndices=u16@1fcb365d130, boneWeights=f32@1fcb05fe6f0, vbo=[18, 0, 19, 0, 0, 0, 20, 0, 0]
    mesh 5: boneIndices=u16@1fcba5726a0, boneWeights=f32@1fcba572b50, vbo=[21, 0, 22, 0, 0, 0, 23, 0, 0]
    mesh 6: boneIndices=u16@1fcb365a890, boneWeights=f32@1fcb05fb6c0, vbo=[24, 0, 25, 0, 0, 0, 26, 0, 0]
    mesh 7: boneIndices=u16@1fcba577220, boneWeights=f32@1fcba5776d0, vbo=[27, 0, 28, 0, 0, 0, 29, 0, 0]
    mesh 8: boneIndices=u16@1fcb05ef9c0, boneWeights=f32@1fcba57a580, vbo=[30, 0, 31, 0, 0, 0, 32, 0, 0]
    mesh 9: boneIndices=u16@1fcba582e90, boneWeights=f32@1fcba583350, vbo=[33, 0, 34, 0, 0, 0, 35, 0, 0]
    mesh 10: boneIndices=u16@1fcba5862a0, boneWeights=f32@1fcba586b80, vbo=[36, 0, 37, 0, 0, 0, 38, 0, 0]
    mesh 11: boneIndices=u16@1fcba58c3d0, boneWeights=f32@1fcba58c810, vbo=[39, 0, 40, 0, 0, 0, 41, 0, 0]
    mesh 12: boneIndices=u16@1fcba58f260, boneWeights=f32@1fcba58f6a0, vbo=[42, 0, 43, 0, 0, 0, 44, 0, 0]
    mesh 13: boneIndices=u16@1fcba5920f0, boneWeights=f32@1fcba5926c0, vbo=[45, 0, 46, 0, 0, 0, 47, 0, 0]
    mesh 14: boneIndices=u16@1fcba5960b0, boneWeights=f32@1fcba596680, vbo=[48, 0, 49, 0, 0, 0, 50, 0, 0]
    mesh 15: boneIndices=u16@1fcba59a070, boneWeights=f32@1fcba59a420, vbo=[51, 0, 52, 0, 0, 0, 53, 0, 0]
    mesh 16: boneIndices=u16@1fcba59c890, boneWeights=f32@1fcba59cc40, vbo=[54, 0, 55, 0, 0, 0, 56, 0, 0]
    mesh 17: boneIndices=u16@1fcba59f0b0, boneWeights=f32@1fcba5a05c0, vbo=[57, 0, 58, 0, 0, 0, 59, 0, 0]
    mesh 18: boneIndices=u16@1fcba5ad7f0, boneWeights=f32@1fcba5ae0e0, vbo=[60, 0, 61, 0, 0, 0, 62, 0, 0]
    

    So at this point the issue appears reproducible independently of the Zig wrapper: the underlying raylib C LoadModel() succeeds, but IsModelValid() reports the resulting model as invalid.

    The discrepancy between the loader reporting 14 meshes / 3 materials and the returned Model containing 19 meshes / 4 materials may also be significant and worth investigating.

    I get the same IsModelValid() == false result with greenman.glb from the raylib examples, as well as with a separate animated model downloaded from Mixamo and converted to GLB format. This happens across multiple independently sourced GLB files, so it does not appear to be specific to the robot.glb file itself or to a malformed model asset.

  4. Not-Nik commented on Oct 4, 2026

    @Not-Nik
    Member

    Looks like an issue mostly with raylib itself, so I'd suggest creating an issue on their repo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions