Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Model Animation bug #47

Open
nuclearshadow opened this issue Jun 18, 2024 · 2 comments
Open

Model Animation bug #47

nuclearshadow opened this issue Jun 18, 2024 · 2 comments

Comments

@nuclearshadow
Copy link

Loading 3D skeletal animation or updating model with said animation doesn't seem to work properly. I have tried almost identical pieces of code for both python and the Zig binding for raylib. It works correctly for the zig version.

Here's the comparison:

Python

Screenshot

animation_python

Code

import raylibpy as rl

def main():
    width = 800
    height = 600
    rl.init_window(width, height, "Model animation test")
    rl.set_target_fps(60)

    camera = rl.Camera(
        position = rl.Vector3( x = 0, y = 5, z = 15 ),
        target = rl.Vector3( x = 0, y = 0, z = 0 ),
        up = rl.Vector3( x = 0, y = 1, z = 0 ),
        fovy = 45,
        projection = rl.CAMERA_PERSPECTIVE
    )

    modelPath = "resources/3d_models/avatar_rigged.glb"

    model = rl.load_model(modelPath)
    
    animCount = 0
    anims = rl.load_model_animations(modelPath, animCount)
    for anim in anims:
        print("%s" % anim.name)

    anim = anims[0]
    print(f"{anim}")

    frameCounter = 0

    while not rl.window_should_close():
        rl.begin_drawing()
        rl.clear_background(rl.RAYWHITE)

        rl.update_model_animation(model, anim, 0)
        # rl.update_model_animation(model, anim, frameCounter)
        frameCounter = (frameCounter + 1) % anim.frame_count

        rl.begin_mode3d(camera)

        rl.draw_model_ex(model, rl.vector3_zero(), rl.Vector3(1, 0, 0), 0, rl.Vector3(1, 1, 1), rl.WHITE)
        
        rl.end_mode3d()
        
        rl.end_drawing()
    
    model.unload()
    rl.close_window()

if __name__ == '__main__':
    main()

Zig

Screenshot

animation_zig

Code

const std = @import("std");
const rl = @import("raylib");

pub fn main() !void {
    const width = 800;
    const height = 600;
    rl.initWindow(width, height, "Model animation test");
    defer rl.closeWindow();
    rl.setTargetFPS(60);

    var camera = rl.Camera{
        .position = .{ .x = 0, .y = 5, .z = 15 },
        .target = .{ .x = 0, .y = 0, .z = 0 },
        .up = .{ .x = 0, .y = 1, .z = 0 },
        .fovy = 45,
        .projection = .camera_perspective,
    };

    const modelPath = "../resources/3d_models/avatar_rigged.glb";

    var model = rl.loadModel(modelPath);
    defer model.unload();

    const anims = try rl.loadModelAnimations(modelPath);
    for (anims) |anim| {
        std.debug.print("{s}\n", .{anim.name});
    }

    const anim = anims[0];
    std.debug.print("{any}", .{anim});

    var frameCounter: c_int = 0;

    while (!rl.windowShouldClose()) {
        rl.beginDrawing();
        rl.clearBackground(rl.Color.ray_white);

        rl.updateModelAnimation(model, anim, 0);
        // rl.updateModelAnimation(model, anim, frameCounter);
        frameCounter = @mod(frameCounter + 1, anim.frameCount);

        camera.begin();

        model.drawEx(rl.Vector3.zero(), rl.Vector3{ .x = 1, .y = 0, .z = 0 }, 0, rl.Vector3{ .x = 1, .y = 1, .z = 1 }, rl.Color.white);

        camera.end();

        rl.endDrawing();
    }
}

It shows as expected on the zig version but breaks in the python version.

Another thing is that python version seems to load 1 less frame of animation compared to zig version
Here are the log messages for animations loading:

Python

INFO: MODEL: [resources/3d_models/avatar_rigged.glb] Loaded animation: ArmatureAction (3 frames, 0.066667s)
INFO: MODEL: [resources/3d_models/avatar_rigged.glb] Loaded animation: Armature|mixamo.com|Layer0 (3 frames, 0.066667s)

Zig

INFO: MODEL: [../resources/3d_models/avatar_rigged.glb] Loaded animation: ArmatureAction (4 frames, 0.066667s)
INFO: MODEL: [../resources/3d_models/avatar_rigged.glb] Loaded animation: Armature|mixamo.com|Layer0 (4 frames, 0.066667s)

And from my testing with 2 different animations, this only occurred when I used an animation with duplicate or hold keyframes in animation (in blender, don't how gltf stores animation. The animation in the screenshot only has 1 keyframe for the pose at the very beginning and another duplicate keyframe in blender) but not for an animation where every keyframe is unique (again, in blender) for the animation I downloaded from mixamo. I don't know how helpful this bit of information is.

I think the combination of 1 less frame and duplicate keyframes appears to cause this.

@overdev
Copy link
Owner

overdev commented Jun 30, 2024

Hi, @nuclearshadow. Thank you for the feedback and sorry for the delayed response.

I fail to see how this bug could be on the python side of the code, but a little bit of investigation won't hurt.

I imagine as a possibility that the gltf loader had some bugfix that is present in the zig binding binaries but not in the python ones. The python binding is basically glue code and type casting back and forth, so no transformation is done to the values between c and python.

To see if this is the problem, you can do the same comparisson as above by running the "model_loading_gltf" example provided by raylib-py (and hopefully by the raylib zig binding). Also, it is good to check whether the zig binding uses in fact a more recent dll/so/dylib than the ones shipped with raylib-py.

To run the python examples provided with raylib-py, you can either put the *.py file in the same directory of its corresponding *.c example and run from there, or you can pass the directory path of the C example as argument in the prompt. In these ways, the resources can be loaded correctly.

In case the same bug is occurring with the raylib gltf animation example, the next step is probably to update the raylib-py package binaries and hope that this will fix the bug.

@nuclearshadow
Copy link
Author

nuclearshadow commented Jul 13, 2024

I think this issue on the original raylib repo is relevant, which was closed not too long ago, as I see almost the same thing happening in the thread as what happened to me, where bones would be positioned at the origin instead of where they should be. It was something to do with bone hierarchy.

Also the fact that the zig bindings I use are on the 5.1-dev version of raylib, so the fix is probably there also.

As such I think eventually updating raylib binaries should fix the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants