raylib-py
raylib-py copied to clipboard
Model Animation bug
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
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
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.