diff --git a/Examples/Models/LoadingGltf.cs b/Examples/Models/LoadingGltf.cs new file mode 100644 index 0000000..586ff19 --- /dev/null +++ b/Examples/Models/LoadingGltf.cs @@ -0,0 +1,123 @@ +/******************************************************************************************* +* +* raylib [models] example - loading gltf +* +* Example complexity rating: [★☆☆☆] 1/4 +* +* LIMITATIONS: +* - Only supports 1 armature per file, and skips loading it if there are multiple armatures +* - Only supports linear interpolation (default method in Blender when checked +* "Always Sample Animations" when exporting a GLTF file) +* - Only supports translation/rotation/scale animation channel.path, +* weights not considered (i.e. morph targets) +* +* Example originally created with raylib 3.7, last time updated with raylib 4.2 +* +* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, +* BSD-like license that allows static linking with closed source software +* +* Copyright (c) 2020-2025 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +using System.Numerics; +using System.Runtime.InteropServices; +using static Raylib_cs.Raylib; + +namespace Examples.Models; + +public class LoadingGltf +{ + public static int Main() + { + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [models] example - loading gltf"); + + // Define the camera to look into our 3d world + Camera3D camera = new(); + camera.Position = new Vector3(6.0f, 6.0f, 6.0f); + camera.Target = new Vector3(0.0f, 2.0f, 0.0f); + camera.Up = new Vector3(0.0f, 1.0f, 0.0f); + camera.FovY = 45.0f; + camera.Projection = CameraProjection.Perspective; + + Model model = LoadModel("resources/models/gltf/robot.glb"); + Vector3 position = new(0.0f, 0.0f, 0.0f); + + // Load animation data + var anims = LoadModelAnimations("resources/models/gltf/robot.glb"); + + // Animation playing variables + int animIndex = 0; + float animCurrentFrame = 0.0f; + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) + { + // Update + //---------------------------------------------------------------------------------- + UpdateCamera(ref camera, CameraMode.Orbital); + + if (IsKeyPressed(KeyboardKey.Right)) + { + animIndex = (animIndex + 1)%anims.Length; + } + else if (IsKeyPressed(KeyboardKey.Left)) + { + animIndex = (animIndex + anims.Length - 1)%anims.Length; + } + + + // Update model animation + animCurrentFrame = (animCurrentFrame + 1)%anims[animIndex].KeyFrameCount; + UpdateModelAnimation(model, anims[animIndex], (float)animCurrentFrame); + + if (animCurrentFrame >= anims[0].KeyFrameCount) + { + animCurrentFrame = 0; + } + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + ClearBackground(Color.RayWhite); + + BeginMode3D(camera); + + DrawModel( + model, + position, + 1f, + Color.White + ); + + DrawGrid(10, 1.0f); + + EndMode3D(); + DrawText($"Current animation: {anims[animIndex].NameToString()}", 10, 40, 20, Color.Maroon); + DrawText("Use the LEFT/RIGHT keys to switch animation", 10, 10, 20, Color.Gray); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadModelAnimations(anims); + UnloadModel(model); + + CloseWindow(); + //-------------------------------------------------------------------------------------- + + return 0; + } +} + diff --git a/Examples/Models/ModelLoading.cs b/Examples/Models/ModelLoading.cs index b714a73..9a84d06 100644 --- a/Examples/Models/ModelLoading.cs +++ b/Examples/Models/ModelLoading.cs @@ -64,7 +64,7 @@ public class ModelLoading { // Update //---------------------------------------------------------------------------------- - UpdateCamera(ref camera, CameraMode.Free); + UpdateCamera(ref camera, CameraMode.Orbital); if (IsFileDropped()) { diff --git a/Examples/Program.cs b/Examples/Program.cs index 27e8996..ca374bf 100644 --- a/Examples/Program.cs +++ b/Examples/Program.cs @@ -113,6 +113,7 @@ public class ExampleList // Models new ExampleInfo("LoadingIqm", LoadingIqm.Main), + new ExampleInfo("LoadingGltf", LoadingGltf.Main), new ExampleInfo("BillboardDemo", BillboardDemo.Main), new ExampleInfo("BoxCollisions", BoxCollisions.Main), new ExampleInfo("CubicmapDemo", CubicmapDemo.Main), @@ -129,6 +130,7 @@ public class ExampleList new ExampleInfo("SkyboxDemo", SkyboxDemo.Main), new ExampleInfo("WavingCubes", WavingCubes.Main), new ExampleInfo("YawPitchRoll", YawPitchRoll.Main), + new ExampleInfo("DynamicMesh", DynamicMesh.Main), // Shaders new ExampleInfo("BasicLighting", BasicLighting.Main), diff --git a/Raylib-cs.Tests/RaylibTests.cs b/Raylib-cs.Tests/RaylibTests.cs index e1962d0..eefdbc0 100644 --- a/Raylib-cs.Tests/RaylibTests.cs +++ b/Raylib-cs.Tests/RaylibTests.cs @@ -40,6 +40,7 @@ public class RaylibTests CheckType(); CheckType(); CheckType(); + CheckType(); CheckType(); CheckType(); CheckType(); diff --git a/Raylib-cs/types/Mesh.cs b/Raylib-cs/types/Mesh.cs index f4bf087..b17e01c 100644 --- a/Raylib-cs/types/Mesh.cs +++ b/Raylib-cs/types/Mesh.cs @@ -198,6 +198,16 @@ public unsafe struct Mesh /// public float* BoneWeights = default; + /// + /// Animated vertex positions after bones transformations, CPU skinning + /// + public float* AnimVertices = default; + + /// + /// Animated normals after bones transformations, CPU skinning + /// + public float* AnimNormals = default; + #endregion #region OpenGL identifiers