Merge pull request #12 from raysan5/master

Update raylib
This commit is contained in:
Thomas Anderson 2026-02-19 19:29:14 -06:00 • committed by GitHub
commit 7fff975121
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
66 changed files with 16159 additions and 6814 deletions

View file

@ -63,7 +63,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers
| [raylib_odin_bindings](https://github.com/Deathbat2190/raylib_odin_bindings) | 4.0-dev | [Odin](https://odin-lang.org) | MIT |
| [raylib-ocaml](https://github.com/tjammer/raylib-ocaml) | **5.0** | [OCaml](https://ocaml.org) | MIT |
| [TurboRaylib](https://github.com/turborium/TurboRaylib) | 4.5 | [Object Pascal](https://en.wikipedia.org/wiki/Object_Pascal) | MIT |
| [Ray4Laz](https://github.com/GuvaCode/Ray4Laz) | **5.5** | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal) | Zlib |
| [Ray4Laz](https://github.com/GuvaCode/Ray4Laz) | **5.5** | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal)/[Delphi](https://en.wikipedia.org/wiki/Delphi_(software)) | Zlib |
| [Raylib.4.0.Pascal](https://github.com/sysrpl/Raylib.4.0.Pascal) | 4.0 | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal) | Zlib |
| [pyraylib](https://github.com/Ho011/pyraylib) | 3.7 | [Python](https://www.python.org) | Zlib |
| [raylib-python-cffi](https://github.com/electronstudio/raylib-python-cffi) | **5.5** | [Python](https://www.python.org) | EPL-2.0 |
@ -185,4 +185,4 @@ Missing some language or wrapper? Feel free to create a new one! :)
Usually, raylib bindings follow the convention: `raylib-{language}`
Let me know if you're writing a new binding for raylib, I will list it here!
Let me know if you're writing a new binding for raylib, I will list it here!

View file

@ -393,14 +393,14 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
# NOTE: Required packages: libegl1-mesa-dev
LDLIBS = -lraylib -lGL -lm -lpthread -ldl -lrt
# On X11 requires also below libraries
LDLIBS += -lX11
# NOTE: It seems additional libraries are not required any more, latest GLFW just dlopen them
#LDLIBS += -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
# On Wayland windowing system, additional libraries requires
# On Wayland, additional libraries requires
ifeq ($(USE_WAYLAND_DISPLAY),TRUE)
LDLIBS += -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon
else
# On X11, additional libraries required
LDLIBS += -lX11
# NOTE: It seems additional libraries are not required any more, latest GLFW just dlopen them
#LDLIBS += -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
endif
# Explicit link to libc
ifeq ($(RAYLIB_LIBTYPE),SHARED)
@ -439,15 +439,16 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL)
# NOTE: Required packages: libegl1-mesa-dev
LDLIBS = -lraylib $(SDL_LIBRARIES) -lGL -lm -lpthread -ldl -lrt
# On X11 requires also below libraries
# On X11, addition libraries required
LDLIBS += -lX11
# NOTE: It seems additional libraries are not required any more, latest GLFW just dlopen them
#LDLIBS += -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
# On Wayland windowing system, additional libraries requires
# On Wayland, additional libraries requires
ifeq ($(USE_WAYLAND_DISPLAY),TRUE)
LDLIBS += -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon
endif
# Explicit link to libc
ifeq ($(RAYLIB_LIBTYPE),SHARED)
LDLIBS += -lc
@ -560,6 +561,7 @@ CORE = \
core/core_window_flags \
core/core_window_letterbox \
core/core_window_should_close \
core/core_window_web \
core/core_world_screen
SHAPES = \
@ -577,6 +579,7 @@ SHAPES = \
shapes/shapes_easings_ball \
shapes/shapes_easings_box \
shapes/shapes_easings_rectangles \
shapes/shapes_easings_testbed \
shapes/shapes_following_eyes \
shapes/shapes_hilbert_curve \
shapes/shapes_kaleidoscope \
@ -654,6 +657,8 @@ TEXT = \
text/text_writing_anim
MODELS = \
models/models_animation_blending \
models/models_animation_bone_blending \
models/models_animation_gpu_skinning \
models/models_animation_playing \
models/models_basic_voxel \
@ -706,6 +711,7 @@ SHADERS = \
shaders/shaders_palette_switch \
shaders/shaders_postprocessing \
shaders/shaders_raymarching_rendering \
shaders/shaders_rlgl_compute \
shaders/shaders_rounded_rectangle \
shaders/shaders_shadowmap_rendering \
shaders/shaders_shapes_textures \
@ -727,14 +733,6 @@ AUDIO = \
audio/audio_sound_positioning \
audio/audio_spectrum_visualizer \
audio/audio_stream_effects
OTHERS = \
others/easings_testbed \
others/embedded_files_loading \
others/raylib_opengl_interop \
others/rlgl_compute_shader \
others/rlgl_standalone \
others/web_basic_window
#EXAMPLES_LIST_END
# Define processes to execute

View file

@ -546,6 +546,7 @@ CORE = \
core/core_window_flags \
core/core_window_letterbox \
core/core_window_should_close \
core/core_window_web \
core/core_world_screen
SHAPES = \
@ -563,6 +564,7 @@ SHAPES = \
shapes/shapes_easings_ball \
shapes/shapes_easings_box \
shapes/shapes_easings_rectangles \
shapes/shapes_easings_testbed \
shapes/shapes_following_eyes \
shapes/shapes_hilbert_curve \
shapes/shapes_kaleidoscope \
@ -640,6 +642,8 @@ TEXT = \
text/text_writing_anim
MODELS = \
models/models_animation_blending \
models/models_animation_bone_blending \
models/models_animation_gpu_skinning \
models/models_animation_playing \
models/models_basic_voxel \
@ -692,6 +696,7 @@ SHADERS = \
shaders/shaders_palette_switch \
shaders/shaders_postprocessing \
shaders/shaders_raymarching_rendering \
shaders/shaders_rlgl_compute \
shaders/shaders_rounded_rectangle \
shaders/shaders_shadowmap_rendering \
shaders/shaders_shapes_textures \
@ -871,6 +876,9 @@ core/core_window_letterbox: core/core_window_letterbox.c
core/core_window_should_close: core/core_window_should_close.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
core/core_window_web: core/core_window_web.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
core/core_world_screen: core/core_world_screen.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@ -917,6 +925,9 @@ shapes/shapes_easings_box: shapes/shapes_easings_box.c
shapes/shapes_easings_rectangles: shapes/shapes_easings_rectangles.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_easings_testbed: shapes/shapes_easings_testbed.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_following_eyes: shapes/shapes_following_eyes.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@ -1188,6 +1199,18 @@ text/text_writing_anim: text/text_writing_anim.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
# Compile MODELS examples
models/models_animation_blending: models/models_animation_blending.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file models/resources/models/gltf/robot.glb@resources/models/gltf/robot.glb \
--preload-file models/resources/shaders/glsl100/skinning.vs@resources/shaders/glsl100/skinning.vs \
--preload-file models/resources/shaders/glsl100/skinning.fs@resources/shaders/glsl100/skinning.fs
models/models_animation_bone_blending: models/models_animation_bone_blending.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file models/resources/models/gltf/greenman.glb@resources/models/gltf/greenman.glb \
--preload-file models/resources/shaders/glsl100/skinning.vs@resources/shaders/glsl100/skinning.vs \
--preload-file models/resources/shaders/glsl100/skinning.fs@resources/shaders/glsl100/skinning.fs
models/models_animation_gpu_skinning: models/models_animation_gpu_skinning.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file models/resources/models/gltf/greenman.glb@resources/models/gltf/greenman.glb \
@ -1461,6 +1484,9 @@ shaders/shaders_raymarching_rendering: shaders/shaders_raymarching_rendering.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file shaders/resources/shaders/glsl100/raymarching.fs@resources/shaders/glsl100/raymarching.fs
shaders/shaders_rlgl_compute: shaders/shaders_rlgl_compute.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shaders/shaders_rounded_rectangle: shaders/shaders_rounded_rectangle.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file shaders/resources/shaders/glsl100/base.vs@resources/shaders/glsl100/base.vs \

View file

@ -17,9 +17,9 @@ You may find it easier to use than other toolchains, especially when it comes to
- `zig build [module]` to compile all examples for a module (e.g. `zig build core`)
- `zig build [example]` to compile _and run_ a particular example (e.g. `zig build core_basic_window`)
## EXAMPLES COLLECTION [TOTAL: 208]
## EXAMPLES COLLECTION [TOTAL: 207]
### category: core [48]
### category: core [49]
Examples using raylib [core](../src/rcore.c) module platform functionality: window creation, inputs, drawing modes and system functionality.
@ -73,8 +73,9 @@ Examples using raylib [core](../src/rcore.c) module platform functionality: wind
| [core_text_file_loading](core/core_text_file_loading.c) | <img src="core/core_text_file_loading.png" alt="core_text_file_loading" width="80"> | ⭐☆☆☆ | 5.5 | 5.6 | [Aanjishnu Bhattacharyya](https://github.com/NimComPoo-04) |
| [core_compute_hash](core/core_compute_hash.c) | <img src="core/core_compute_hash.png" alt="core_compute_hash" width="80"> | ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) |
| [core_keyboard_testbed](core/core_keyboard_testbed.c) | <img src="core/core_keyboard_testbed.png" alt="core_keyboard_testbed" width="80"> | ⭐⭐☆☆ | 5.6 | 5.6 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_window_web](core/core_window_web.c) | <img src="core/core_window_web.png" alt="core_window_web" width="80"> | ⭐☆☆☆ | 1.3 | 5.5 | [Ramon Santamaria](https://github.com/raysan5) |
### category: shapes [39]
### category: shapes [40]
Examples using raylib shapes drawing functionality, provided by raylib [shapes](../src/rshapes.c) module.
@ -119,6 +120,7 @@ Examples using raylib shapes drawing functionality, provided by raylib [shapes](
| [shapes_ball_physics](shapes/shapes_ball_physics.c) | <img src="shapes/shapes_ball_physics.png" alt="shapes_ball_physics" width="80"> | ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [David Buzatto](https://github.com/davidbuzatto) |
| [shapes_penrose_tile](shapes/shapes_penrose_tile.c) | <img src="shapes/shapes_penrose_tile.png" alt="shapes_penrose_tile" width="80"> | ⭐⭐⭐⭐️ | 5.5 | 5.6-dev | [David Buzatto](https://github.com/davidbuzatto) |
| [shapes_hilbert_curve](shapes/shapes_hilbert_curve.c) | <img src="shapes/shapes_hilbert_curve.png" alt="shapes_hilbert_curve" width="80"> | ⭐⭐⭐☆ | 5.6 | 5.6 | [Hamza RAHAL](https://github.com/hmz-rhl) |
| [shapes_easings_testbed](shapes/shapes_easings_testbed.c) | <img src="shapes/shapes_easings_testbed.png" alt="shapes_easings_testbed" width="80"> | ⭐⭐⭐☆ | 2.5 | 2.5 | [Juan Miguel López](https://github.com/flashback-fx) |
### category: textures [30]
@ -180,7 +182,7 @@ Examples using raylib text functionality, including sprite fonts loading/generat
| [text_words_alignment](text/text_words_alignment.c) | <img src="text/text_words_alignment.png" alt="text_words_alignment" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) |
| [text_strings_management](text/text_strings_management.c) | <img src="text/text_strings_management.png" alt="text_strings_management" width="80"> | ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [David Buzatto](https://github.com/davidbuzatto) |
### category: models [27]
### category: models [29]
Examples using raylib models functionality, including models loading/generation and drawing, provided by raylib [models](../src/rmodels.c) module.
@ -213,8 +215,10 @@ Examples using raylib models functionality, including models loading/generation
| [models_rotating_cube](models/models_rotating_cube.c) | <img src="models/models_rotating_cube.png" alt="models_rotating_cube" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Jopestpe](https://github.com/jopestpe) |
| [models_decals](models/models_decals.c) | <img src="models/models_decals.png" alt="models_decals" width="80"> | ⭐⭐⭐⭐️ | 5.6-dev | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) |
| [models_directional_billboard](models/models_directional_billboard.c) | <img src="models/models_directional_billboard.png" alt="models_directional_billboard" width="80"> | ⭐⭐☆☆ | 5.6-dev | 5.6 | [Robin](https://github.com/RobinsAviary) |
| [models_animation_bone_blending](models/models_animation_bone_blending.c) | <img src="models/models_animation_bone_blending.png" alt="models_animation_bone_blending" width="80"> | ⭐⭐⭐⭐️ | 5.5 | 5.5 | [dmitrii-brand](https://github.com/dmitrii-brand) |
| [models_animation_blending](models/models_animation_blending.c) | <img src="models/models_animation_blending.png" alt="models_animation_blending" width="80"> | ☆☆☆☆ | 5.5 | 5.6-dev | [Kirandeep](https://github.com/Kirandeep-Singh-Khehra) |
### category: shaders [33]
### category: shaders [34]
Examples using raylib shaders functionality, including shaders loading, parameters configuration and drawing using them (model shaders and postprocessing shaders). This functionality is directly provided by raylib [rlgl](../src/rlgl.c) module.
@ -253,6 +257,7 @@ Examples using raylib shaders functionality, including shaders loading, paramete
| [shaders_rounded_rectangle](shaders/shaders_rounded_rectangle.c) | <img src="shaders/shaders_rounded_rectangle.png" alt="shaders_rounded_rectangle" width="80"> | ⭐⭐⭐☆ | 5.5 | 5.5 | [Anstro Pleuton](https://github.com/anstropleuton) |
| [shaders_depth_rendering](shaders/shaders_depth_rendering.c) | <img src="shaders/shaders_depth_rendering.png" alt="shaders_depth_rendering" width="80"> | ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [Luís Almeida](https://github.com/luis605) |
| [shaders_game_of_life](shaders/shaders_game_of_life.c) | <img src="shaders/shaders_game_of_life.png" alt="shaders_game_of_life" width="80"> | ⭐⭐⭐☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) |
| [shaders_rlgl_compute](shaders/shaders_rlgl_compute.c) | <img src="shaders/shaders_rlgl_compute.png" alt="shaders_rlgl_compute" width="80"> | ⭐⭐⭐⭐️ | 4.0 | 4.0 | [Teddy Astie](https://github.com/tsnake41) |
### category: audio [9]
@ -270,18 +275,5 @@ Examples using raylib audio functionality, including sound/music loading and pla
| [audio_sound_positioning](audio/audio_sound_positioning.c) | <img src="audio/audio_sound_positioning.png" alt="audio_sound_positioning" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [Le Juez Victor](https://github.com/Bigfoot71) |
| [audio_spectrum_visualizer](audio/audio_spectrum_visualizer.c) | <img src="audio/audio_spectrum_visualizer.png" alt="audio_spectrum_visualizer" width="80"> | ⭐⭐⭐☆ | 6.0 | 5.6-dev | [IANN](https://github.com/meisei4) |
### category: others [6]
Examples showing raylib misc functionality that does not fit in other categories, like standalone modules usage or examples integrating external libraries.
| example | image | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer |
|-----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
| [rlgl_standalone](others/rlgl_standalone.c) | <img src="others/rlgl_standalone.png" alt="rlgl_standalone" width="80"> | ⭐⭐⭐⭐️ | 1.6 | 4.0 | [Ramon Santamaria](https://github.com/raysan5) |
| [rlgl_compute_shader](others/rlgl_compute_shader.c) | <img src="others/rlgl_compute_shader.png" alt="rlgl_compute_shader" width="80"> | ⭐⭐⭐⭐️ | 4.0 | 4.0 | [Teddy Astie](https://github.com/tsnake41) |
| [easings_testbed](others/easings_testbed.c) | <img src="others/easings_testbed.png" alt="easings_testbed" width="80"> | ⭐⭐⭐☆ | 2.5 | 3.0 | [Juan Miguel López](https://github.com/flashback-fx) |
| [raylib_opengl_interop](others/raylib_opengl_interop.c) | <img src="others/raylib_opengl_interop.png" alt="raylib_opengl_interop" width="80"> | ⭐⭐⭐⭐️ | 3.8 | 4.0 | [Stephan Soller](https://github.com/arkanis) |
| [embedded_files_loading](others/embedded_files_loading.c) | <img src="others/embedded_files_loading.png" alt="embedded_files_loading" width="80"> | ⭐⭐☆☆ | 3.0 | 3.5 | [Kristian Holmgren](https://github.com/defutura) |
| [web_basic_window](others/web_basic_window.c) | <img src="others/web_basic_window.png" alt="web_basic_window" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) |
Some example missing? As always, contributions are welcome, feel free to send new examples!
Here is an [examples template](examples_template.c) with instructions to start with!

View file

@ -68,7 +68,7 @@ int main(void)
.z = 5.0f*sinf(th)
};
SetSoundPosition(camera, sound, spherePos, 20.0f);
SetSoundPosition(camera, sound, spherePos, 1.0f);
if (!IsSoundPlaying(sound)) PlaySound(sound);
//----------------------------------------------------------------------------------

View file

@ -148,10 +148,11 @@ int main(void)
DrawText("Controls:", 20, 20, 10, BLACK);
DrawText("- Right/Left to move", 40, 40, 10, DARKGRAY);
DrawText("- Space to jump", 40, 60, 10, DARKGRAY);
DrawText("- Mouse Wheel to Zoom in-out, R to reset zoom", 40, 80, 10, DARKGRAY);
DrawText("- C to change camera mode", 40, 100, 10, DARKGRAY);
DrawText("Current camera mode:", 20, 120, 10, BLACK);
DrawText(cameraDescriptions[cameraOption], 40, 140, 10, DARKGRAY);
DrawText("- Mouse Wheel to Zoom in-out", 40, 80, 10, DARKGRAY);
DrawText("- R to reset position + zoom", 40, 100, 10, DARKGRAY);
DrawText("- C to change camera mode", 40, 120, 10, DARKGRAY);
DrawText("Current camera mode:", 20, 140, 10, BLACK);
DrawText(cameraDescriptions[cameraOption], 40, 160, 10, DARKGRAY);
EndDrawing();
//----------------------------------------------------------------------------------

View file

@ -37,10 +37,18 @@ int main(void)
char directory[MAX_FILEPATH_SIZE] = { 0 };
strcpy(directory, GetWorkingDirectory());
FilePathList files = LoadDirectoryFiles(directory);
// Load file-paths on current working directory
// NOTE: LoadDirectoryFiles() loads files and directories by default,
// use LoadDirectoryFilesEx() for custom filters and recursive directories loading
//FilePathList files = LoadDirectoryFiles(directory);
FilePathList files = LoadDirectoryFilesEx(directory, ".png;.c", false);
int btnBackPressed = false;
int listScrollIndex = 0;
int listItemActive = -1;
int listItemFocused = -1;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
@ -62,10 +70,18 @@ int main(void)
BeginDrawing();
ClearBackground(RAYWHITE);
DrawText(directory, 100, 40, 20, DARKGRAY);
btnBackPressed = GuiButton((Rectangle){ 40.0f, 10.0f, 48, 28 }, "<");
btnBackPressed = GuiButton((Rectangle){ 40.0f, 38.0f, 48, 24 }, "<");
GuiSetStyle(DEFAULT, TEXT_SIZE, GuiGetFont().baseSize*2);
GuiLabel((Rectangle){ 40 + 48 + 10, 10, 700, 28 }, directory);
GuiSetStyle(DEFAULT, TEXT_SIZE, GuiGetFont().baseSize);
GuiSetStyle(LISTVIEW, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
GuiSetStyle(LISTVIEW, TEXT_PADDING, 40);
GuiListViewEx((Rectangle){ 0, 50, GetScreenWidth(), GetScreenHeight() - 50 },
files.paths, files.count, &listScrollIndex, &listItemActive, &listItemFocused);
/*
for (int i = 0; i < (int)files.count; i++)
{
Color color = Fade(LIGHTGRAY, 0.3f);
@ -84,6 +100,7 @@ int main(void)
DrawRectangle(0, 85 + 40*i, screenWidth, 40, color);
DrawText(GetFileName(files.paths[i]), 120, 100 + 40*i, 10, GRAY);
}
*/
EndDrawing();
//----------------------------------------------------------------------------------

View file

@ -78,7 +78,7 @@ int main(void)
DrawText(TextFormat("WINDOW POSITION: %ix%i", (int)windowPos.x, (int)windowPos.y), 50, 90, 20, DARKGRAY);
DrawText(TextFormat("SCREEN SIZE: %ix%i", GetScreenWidth(), GetScreenHeight()), 50, 130, 20, DARKGRAY);
DrawText(TextFormat("RENDER SIZE: %ix%i", GetRenderWidth(), GetRenderHeight()), 50, 170, 20, DARKGRAY);
DrawText(TextFormat("SCALE FACTOR: %.1fx%.1f", scaleDpi.x, scaleDpi.y), 50, 210, 20, GRAY);
DrawText(TextFormat("SCALE FACTOR: %.2fx%.2f", scaleDpi.x, scaleDpi.y), 50, 210, 20, GRAY);
// Draw reference rectangles, top-left and bottom-right corners
DrawRectangle(0, 0, 30, 60, RED);

View file

@ -117,7 +117,7 @@ int main(void)
DrawRectangleV(position, size, releaseAction? BLUE : RED);
DrawText((actionSet == 0)? "Current input set: WASD (default)" : "Current input set: Cursor", 10, 10, 20, WHITE);
DrawText((actionSet == 0)? "Current input set: WASD (default)" : "Current input set: Arrow keys", 10, 10, 20, WHITE);
DrawText("Use TAB key to toggles Actions keyset", 10, 50, 20, GREEN);
EndDrawing();

View file

@ -24,7 +24,8 @@
// NOTE: Gamepad name ID depends on drivers and OS
#define XBOX_ALIAS_1 "xbox"
#define XBOX_ALIAS_2 "x-box"
#define PS_ALIAS "playstation"
#define PS_ALIAS_1 "playstation"
#define PS_ALIAS_2 "sony"
//------------------------------------------------------------------------------------
// Program main entry point
@ -148,7 +149,8 @@ int main(void)
//DrawText(TextFormat("Xbox axis LT: %02.02f", GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_LEFT_TRIGGER)), 10, 40, 10, BLACK);
//DrawText(TextFormat("Xbox axis RT: %02.02f", GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_RIGHT_TRIGGER)), 10, 60, 10, BLACK);
}
else if (TextFindIndex(TextToLower(GetGamepadName(gamepad)), PS_ALIAS) > -1)
else if ((TextFindIndex(TextToLower(GetGamepadName(gamepad)), PS_ALIAS_1) > -1) ||
(TextFindIndex(TextToLower(GetGamepadName(gamepad)), PS_ALIAS_2) > -1))
{
DrawTexture(texPs3Pad, 0, 0, DARKGRAY);

View file

@ -51,11 +51,31 @@ int main(void)
{ padPosition.x, padPosition.y + buttonRadius*1.5f } // Down
};
const char *buttonLabels[BUTTON_MAX] = {
"Y", // Up
"X", // Left
"B", // Right
"A" // Down
Vector2 arrowTris[4][3] = {
// Up
{
{ buttonPositions[0].x, buttonPositions[0].y - 12 },
{ buttonPositions[0].x - 9, buttonPositions[0].y + 9 },
{ buttonPositions[0].x + 9, buttonPositions[0].y + 9 }
},
// Left
{
{ buttonPositions[1].x + 9, buttonPositions[1].y - 9 },
{ buttonPositions[1].x - 12, buttonPositions[1].y },
{ buttonPositions[1].x + 9, buttonPositions[1].y + 9 }
},
// Right
{
{ buttonPositions[2].x + 12, buttonPositions[2].y },
{ buttonPositions[2].x - 9, buttonPositions[2].y - 9 },
{ buttonPositions[2].x - 9, buttonPositions[2].y + 9 }
},
// Down
{
{ buttonPositions[3].x - 9, buttonPositions[3].y - 9 },
{ buttonPositions[3].x, buttonPositions[3].y + 12 },
{ buttonPositions[3].x + 9, buttonPositions[3].y - 9 }
}
};
Color buttonLabelColors[BUTTON_MAX] = {
@ -128,9 +148,12 @@ int main(void)
{
DrawCircleV(buttonPositions[i], buttonRadius, (i == pressedButton)? DARKGRAY : BLACK);
DrawText(buttonLabels[i],
(int)buttonPositions[i].x - 7, (int)buttonPositions[i].y - 8,
20, buttonLabelColors[i]);
DrawTriangle(
arrowTris[i][0],
arrowTris[i][1],
arrowTris[i][2],
buttonLabelColors[i]
);
}
DrawText("move the player with D-Pad buttons", 10, 10, 20, DARKGRAY);

View file

@ -96,8 +96,6 @@ int main(void)
{
DrawRectangleRec(rectangles[i].rect, rectangles[i].color);
DrawText("Press SPACE to shuffle the sequence", 10, screenHeight - 96, 20, BLACK);
DrawText("Press SPACE to shuffle the current sequence", 10, screenHeight - 96, 20, BLACK);
DrawText("Press UP to add a rectangle and generate a new sequence", 10, screenHeight - 64, 20, BLACK);
DrawText("Press DOWN to remove a rectangle and generate a new sequence", 10, screenHeight - 32, 20, BLACK);

View file

@ -0,0 +1,86 @@
/*******************************************************************************************
*
* raylib [core] example - window web
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 1.3, last time updated with raylib 5.5
*
* This example has been adapted to compile for PLATFORM_WEB and PLATFORM_DESKTOP
* As you will notice, code structure is slightly different to the other examples
*
* 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) 2015-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#if defined(PLATFORM_WEB)
#include <emscripten/emscripten.h>
#endif
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
int screenWidth = 800;
int screenHeight = 450;
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
void UpdateDrawFrame(void); // Update and Draw one frame
//----------------------------------------------------------------------------------
// Program main entry point
//----------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
InitWindow(screenWidth, screenHeight, "raylib [core] example - window web");
#if defined(PLATFORM_WEB)
emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
#else
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
UpdateDrawFrame();
}
#endif
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
void UpdateDrawFrame(void)
{
// Update
//----------------------------------------------------------------------------------
// TODO: Update your variables here
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
DrawText("Welcome to raylib web structure!", 220, 200, 20, SKYBLUE);
EndDrawing();
//----------------------------------------------------------------------------------
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

File diff suppressed because it is too large Load diff

View file

@ -57,6 +57,7 @@ core;core_clipboard_text;★★☆☆;5.6-dev;5.6-dev;2025;2025;"Ananth S";@Anan
core;core_text_file_loading;★☆☆☆;5.5;5.6;0;0;"Aanjishnu Bhattacharyya";@NimComPoo-04
core;core_compute_hash;★★☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5
core;core_keyboard_testbed;★★☆☆;5.6;5.6;2026;2026;"Ramon Santamaria";@raysan5
core;core_window_web;★☆☆☆;1.3;5.5;2015;2025;"Ramon Santamaria";@raysan5
shapes;shapes_basic_shapes;★☆☆☆;1.0;4.2;2014;2025;"Ramon Santamaria";@raysan5
shapes;shapes_bouncing_ball;★☆☆☆;2.5;2.5;2013;2025;"Ramon Santamaria";@raysan5
shapes;shapes_bullet_hell;★☆☆☆;5.6;5.6;2025;2025;"Zero";@zerohorsepower
@ -96,6 +97,7 @@ shapes;shapes_rlgl_triangle;★★☆☆;5.6-dev;5.6-dev;2025;2025;"Robin";@Robi
shapes;shapes_ball_physics;★★☆☆;5.6-dev;5.6-dev;2025;2025;"David Buzatto";@davidbuzatto
shapes;shapes_penrose_tile;★★★★;5.5;5.6-dev;2025;2025;"David Buzatto";@davidbuzatto
shapes;shapes_hilbert_curve;★★★☆;5.6;5.6;2025;2025;"Hamza RAHAL";@hmz-rhl
shapes;shapes_easings_testbed;★★★☆;2.5;2.5;2019;2025;"Juan Miguel López";@flashback-fx
textures;textures_logo_raylib;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5
textures;textures_srcrec_dstrec;★★★☆;1.3;1.3;2015;2025;"Ramon Santamaria";@raysan5
textures;textures_image_drawing;★★☆☆;1.4;1.4;2016;2025;"Ramon Santamaria";@raysan5
@ -169,6 +171,8 @@ models;models_basic_voxel;★★☆☆;5.5;5.5;2025;2025;"Tim Little";@timlittle
models;models_rotating_cube;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Jopestpe";@jopestpe
models;models_decals;★★★★;5.6-dev;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates
models;models_directional_billboard;★★☆☆;5.6-dev;5.6;2025;2025;"Robin";@RobinsAviary
models;models_animation_bone_blending;★★★★;5.5;5.5;2026;2026;"dmitrii-brand";@dmitrii-brand
models;models_animation_blending;☆☆☆☆;5.5;5.6-dev;2024;2024;"Kirandeep";@Kirandeep-Singh-Khehra
shaders;shaders_ascii_rendering;★★☆☆;5.5;5.6;2025;2025;"Maicon Santana";@maiconpintoabreu
shaders;shaders_basic_lighting;★★★★;3.0;4.2;2019;2025;"Chris Camacho";@chriscamacho
shaders;shaders_model_shader;★★☆☆;1.3;3.7;2014;2025;"Ramon Santamaria";@raysan5
@ -202,6 +206,7 @@ shaders;shaders_lightmap_rendering;★★★☆;4.5;4.5;2019;2025;"Jussi Viitala
shaders;shaders_rounded_rectangle;★★★☆;5.5;5.5;2025;2025;"Anstro Pleuton";@anstropleuton
shaders;shaders_depth_rendering;★★★☆;5.6-dev;5.6-dev;2025;2025;"Luís Almeida";@luis605
shaders;shaders_game_of_life;★★★☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant
shaders;shaders_rlgl_compute;★★★★;4.0;4.0;2021;2025;"Teddy Astie";@tsnake41
audio;audio_module_playing;★☆☆☆;1.5;3.5;2016;2025;"Ramon Santamaria";@raysan5
audio;audio_music_stream;★☆☆☆;1.3;4.2;2015;2025;"Ramon Santamaria";@raysan5
audio;audio_raw_stream;★★★☆;1.6;4.2;2015;2025;"Ramon Santamaria";@raysan5
@ -211,9 +216,3 @@ audio;audio_stream_effects;★★★★;4.2;5.0;2022;2025;"Ramon Santamaria";@ra
audio;audio_sound_multi;★★☆☆;5.0;5.0;2023;2025;"Jeffery Myers";@JeffM2501
audio;audio_sound_positioning;★★☆☆;5.5;5.5;2025;2025;"Le Juez Victor";@Bigfoot71
audio;audio_spectrum_visualizer;★★★☆;6.0;5.6-dev;2025;2025;"IANN";@meisei4
others;rlgl_standalone;★★★★;1.6;4.0;2014;2025;"Ramon Santamaria";@raysan5
others;rlgl_compute_shader;★★★★;4.0;4.0;2021;2025;"Teddy Astie";@tsnake41
others;easings_testbed;★★★☆;2.5;3.0;2019;2025;"Juan Miguel López";@flashback-fx
others;raylib_opengl_interop;★★★★;3.8;4.0;2021;2025;"Stephan Soller";@arkanis
others;embedded_files_loading;★★☆☆;3.0;3.5;2020;2025;"Kristian Holmgren";@defutura
others;web_basic_window;★☆☆☆;5.6-dev;5.6-dev;2014;2025;"Ramon Santamaria";@raysan5

View file

@ -0,0 +1,152 @@
/*******************************************************************************************
*
* raylib [models] example - animation blending
*
* Example originally created with raylib 5.5, last time updated with raylib 5.6-dev
*
* Example contributed by Kirandeep (@Kirandeep-Singh-Khehra)
*
* 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) 2024 Kirandeep (@Kirandeep-Singh-Khehra)
*
* Note: Due to limitations in the Apple OpenGL driver, this feature does not work on MacOS
* Note: This example uses CPU for updating meshes.
* For GPU skinning see comments with 'INFO:'.
*
********************************************************************************************/
#include "raylib.h"
#define clamp(x,a,b) ((x < a)? a : (x > b)? b : x)
#if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330
#else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100
#endif
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - animation blending");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 8.0f, 8.0f, 8.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 2.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
// Load gltf model
Model characterModel = LoadModel("resources/models/gltf/robot.glb"); // Load character model
/* INFO: Uncomment this to use GPU skinning
// Load skinning shader
Shader skinningShader = LoadShader(TextFormat("resources/shaders/glsl%i/skinning.vs", GLSL_VERSION),
TextFormat("resources/shaders/glsl%i/skinning.fs", GLSL_VERSION));
for (int i = 0; i < characterModel.materialCount; i++)
{
characterModel.materials[i].shader = skinningShader;
}
*/
// Load gltf model animations
int animsCount = 0;
unsigned int animIndex0 = 0;
unsigned int animIndex1 = 0;
unsigned int animCurrentFrame = 0;
ModelAnimation *modelAnimations = LoadModelAnimations("resources/models/gltf/robot.glb", &animsCount);
float blendFactor = 0.5f;
DisableCursor(); // Limit cursor to relative movement inside the window
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_THIRD_PERSON);
// Select current animation
if (IsKeyPressed(KEY_T)) animIndex0 = (animIndex0 + 1)%animsCount;
else if (IsKeyPressed(KEY_G)) animIndex0 = (animIndex0 + animsCount - 1)%animsCount;
if (IsKeyPressed(KEY_Y)) animIndex1 = (animIndex1 + 1)%animsCount;
else if (IsKeyPressed(KEY_H)) animIndex1 = (animIndex1 + animsCount - 1)%animsCount;
// Select blend factor
if (IsKeyPressed(KEY_U)) blendFactor = clamp(blendFactor - 0.1, 0.0f, 1.0f);
else if (IsKeyPressed(KEY_J)) blendFactor = clamp(blendFactor + 0.1, 0.0f, 1.0f);
// Update animation
animCurrentFrame++;
// Update bones
// Note: Same animation frame index is used below. By default it loops both animations
UpdateModelAnimationBonesLerp(characterModel, modelAnimations[animIndex0], animCurrentFrame, modelAnimations[animIndex1], animCurrentFrame, blendFactor);
// INFO: Comment the following line to use GPU skinning
UpdateModelVertsToCurrentBones(characterModel);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
/* INFO: Uncomment this to use GPU skinning
// Draw character mesh, pose calculation is done in shader (GPU skinning)
for (int i = 0; i < characterModel.meshCount; i++)
{
DrawMesh(characterModel.meshes[i], characterModel.materials[characterModel.meshMaterial[i]], characterModel.transform);
}
*/
// INFO: Comment the following line to use GPU skinning
DrawModel(characterModel, (Vector3){0.0f, 0.0f, 0.0f}, 1.0f, WHITE);
DrawGrid(10, 1.0f);
EndMode3D();
DrawText("Use the U/J to adjust blend factor", 10, 10, 20, GRAY);
DrawText("Use the T/G to switch first animation", 10, 30, 20, GRAY);
DrawText("Use the Y/H to switch second animation", 10, 50, 20, GRAY);
DrawText(TextFormat("Animations: %s, %s", modelAnimations[animIndex0].name, modelAnimations[animIndex1].name), 10, 70, 20, BLACK);
DrawText(TextFormat("Blend Factor: %f", blendFactor), 10, 86, 20, BLACK);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModelAnimations(modelAnimations, animsCount); // Unload model animation
UnloadModel(characterModel); // Unload model and meshes/material
// INFO: Uncomment the following line to use GPU skinning
// UnloadShader(skinningShader); // Unload GPU skinning shader
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View file

@ -0,0 +1,296 @@
/*******************************************************************************************
*
* raylib [models] example - animation bone blending
*
* Example complexity rating: [★★★★] 4/4
*
* Example originally created with raylib 5.5, last time updated with raylib 5.5
*
* This example demonstrates per-bone animation blending, allowing smooth transitions
* between two animations by interpolating bone transforms. This is useful for:
* - Blending movement animations (walk/run) with action animations (jump/attack)
* - Creating smooth animation transitions
* - Layering animations (e.g., upper body attack while lower body walks)
*
* Example contributed by dmitrii-brand (@dmitrii-brand) and reviewed by Ramon Santamaria (@raysan5)
*
* NOTE: Due to limitations in the Apple OpenGL driver, this feature does not work on MacOS
*
* 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) 2026 dmitrii-brand (@dmitrii-brand)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#include <string.h> // Required for: memcpy()
#include <stdlib.h> // Required for: NULL
#if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330
#else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100
#endif
//------------------------------------------------------------------------------------
// Module Functions Declaration
//------------------------------------------------------------------------------------
static bool IsUpperBodyBone(const char *boneName);
static void BlendModelAnimationsBones(Model *model, ModelAnimation *anim1, int frame1,
ModelAnimation *anim2, int frame2, float blendFactor, bool upperBodyBlend);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - animation bone blending");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 5.0f, 5.0f, 5.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 2.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
// Load gltf model
Model characterModel = LoadModel("resources/models/gltf/greenman.glb");
// Load skinning shader
Shader skinningShader = LoadShader(TextFormat("resources/shaders/glsl%i/skinning.vs", GLSL_VERSION),
TextFormat("resources/shaders/glsl%i/skinning.fs", GLSL_VERSION));
characterModel.materials[1].shader = skinningShader;
// Load gltf model animations
int animsCount = 0;
ModelAnimation *modelAnimations = LoadModelAnimations("resources/models/gltf/greenman.glb", &animsCount);
// Log all available animations for debugging
TraceLog(LOG_INFO, "Found %d animations:", animsCount);
for (int i = 0; i < animsCount; i++)
{
TraceLog(LOG_INFO, " Animation %d: %s (%d frames)", i, modelAnimations[i].name, modelAnimations[i].frameCount);
}
// Use specific indices: walk/move = 2, attack = 3
unsigned int animIndex1 = 2; // Walk/Move animation (index 2)
unsigned int animIndex2 = 3; // Attack animation (index 3)
unsigned int animCurrentFrame1 = 0;
unsigned int animCurrentFrame2 = 0;
// Validate indices
if (animIndex1 >= animsCount) animIndex1 = 0;
if (animIndex2 >= animsCount) animIndex2 = (animsCount > 1) ? 1 : 0;
TraceLog(LOG_INFO, "Using Walk (index %d): %s", animIndex1, modelAnimations[animIndex1].name);
TraceLog(LOG_INFO, "Using Attack (index %d): %s", animIndex2, modelAnimations[animIndex2].name);
Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position
bool upperBodyBlend = true; // Toggle: true = upper/lower body blending, false = uniform blending (50/50)
DisableCursor(); // Limit cursor to relative movement inside the window
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_THIRD_PERSON);
// Toggle upper/lower body blending mode (SPACE key)
if (IsKeyPressed(KEY_SPACE)) upperBodyBlend = !upperBodyBlend;
// Update animation frames
ModelAnimation anim1 = modelAnimations[animIndex1];
ModelAnimation anim2 = modelAnimations[animIndex2];
animCurrentFrame1 = (animCurrentFrame1 + 1)%anim1.frameCount;
animCurrentFrame2 = (animCurrentFrame2 + 1)%anim2.frameCount;
// Blend the two animations
characterModel.transform = MatrixTranslate(position.x, position.y, position.z);
// When upperBodyBlend is ON: upper body = attack (1.0), lower body = walk (0.0)
// When upperBodyBlend is OFF: uniform blend at 0.5 (50% walk, 50% attack)
float blendFactor = upperBodyBlend ? 1.0f : 0.5f;
BlendModelAnimationsBones(&characterModel, &anim1, animCurrentFrame1, &anim2, animCurrentFrame2, blendFactor, upperBodyBlend);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
// Draw character mesh, pose calculation is done in shader (GPU skinning)
DrawMesh(characterModel.meshes[0], characterModel.materials[1], characterModel.transform);
DrawGrid(10, 1.0f);
EndMode3D();
// Draw UI
DrawText("BONE BLENDING EXAMPLE", 10, 10, 20, DARKGRAY);
DrawText(TextFormat("Walk (Animation 2): %s", anim1.name), 10, 35, 10, GRAY);
DrawText(TextFormat("Attack (Animation 3): %s", anim2.name), 10, 50, 10, GRAY);
DrawText(TextFormat("Mode: %s", upperBodyBlend ? "Upper/Lower Body Blending" : "Uniform Blending"), 10, 65, 10, GRAY);
DrawText("SPACE - Toggle blending mode", 10, GetScreenHeight() - 20, 10, DARKGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModelAnimations(modelAnimations, animsCount); // Unload model animation
UnloadModel(characterModel); // Unload model and meshes/material
UnloadShader(skinningShader); // Unload GPU skinning shader
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
// Check if a bone is part of upper body (for selective blending)
static bool IsUpperBodyBone(const char *boneName)
{
// Common upper body bone names (adjust based on your model)
if (TextIsEqual(boneName, "spine") || TextIsEqual(boneName, "spine1") || TextIsEqual(boneName, "spine2") ||
TextIsEqual(boneName, "chest") || TextIsEqual(boneName, "upperChest") ||
TextIsEqual(boneName, "neck") || TextIsEqual(boneName, "head") ||
TextIsEqual(boneName, "shoulder") || TextIsEqual(boneName, "shoulder_L") || TextIsEqual(boneName, "shoulder_R") ||
TextIsEqual(boneName, "upperArm") || TextIsEqual(boneName, "upperArm_L") || TextIsEqual(boneName, "upperArm_R") ||
TextIsEqual(boneName, "lowerArm") || TextIsEqual(boneName, "lowerArm_L") || TextIsEqual(boneName, "lowerArm_R") ||
TextIsEqual(boneName, "hand") || TextIsEqual(boneName, "hand_L") || TextIsEqual(boneName, "hand_R") ||
TextIsEqual(boneName, "clavicle") || TextIsEqual(boneName, "clavicle_L") || TextIsEqual(boneName, "clavicle_R"))
{
return true;
}
// Check if bone name contains upper body keywords
if (strstr(boneName, "spine") != NULL || strstr(boneName, "chest") != NULL ||
strstr(boneName, "neck") != NULL || strstr(boneName, "head") != NULL ||
strstr(boneName, "shoulder") != NULL || strstr(boneName, "arm") != NULL ||
strstr(boneName, "hand") != NULL || strstr(boneName, "clavicle") != NULL)
{
return true;
}
return false;
}
// Blend two animations per-bone with selective upper/lower body blending
static void BlendModelAnimationsBones(Model *model, ModelAnimation *anim1, int frame1,
ModelAnimation *anim2, int frame2, float blendFactor, bool upperBodyBlend)
{
// Validate inputs
if (anim1->boneCount == 0 || anim1->framePoses == NULL ||
anim2->boneCount == 0 || anim2->framePoses == NULL ||
model->boneCount == 0 || model->bindPose == NULL)
{
return;
}
// Clamp blend factor to [0, 1]
blendFactor = fminf(1.0f, fmaxf(0.0f, blendFactor));
// Ensure frame indices are valid
if (frame1 >= anim1->frameCount) frame1 = anim1->frameCount - 1;
if (frame2 >= anim2->frameCount) frame2 = anim2->frameCount - 1;
if (frame1 < 0) frame1 = 0;
if (frame2 < 0) frame2 = 0;
// Find first mesh with bones
int firstMeshWithBones = -1;
for (int i = 0; i < model->meshCount; i++)
{
if (model->meshes[i].boneMatrices)
{
firstMeshWithBones = i;
break;
}
}
if (firstMeshWithBones == -1) return;
// Get bone count (use minimum of all to be safe)
int boneCount = model->boneCount;
if (anim1->boneCount < boneCount) boneCount = anim1->boneCount;
if (anim2->boneCount < boneCount) boneCount = anim2->boneCount;
// Blend each bone
for (int boneId = 0; boneId < boneCount; boneId++)
{
// Determine blend factor for this bone
float boneBlendFactor = blendFactor;
// If upper body blending is enabled, use different blend factors for upper vs lower body
if (upperBodyBlend)
{
const char *boneName = model->bones[boneId].name;
bool isUpperBody = IsUpperBodyBone(boneName);
// Upper body: use anim2 (attack), Lower body: use anim1 (walk)
// blendFactor = 0.0 means full anim1 (walk), 1.0 means full anim2 (attack)
if (isUpperBody) boneBlendFactor = blendFactor; // Upper body: blend towards anim2 (attack)
else boneBlendFactor = 1.0f - blendFactor; // Lower body: blend towards anim1 (walk) - invert the blend
}
// Get transforms from both animations
Transform *bindTransform = &model->bindPose[boneId];
Transform *anim1Transform = &anim1->framePoses[frame1][boneId];
Transform *anim2Transform = &anim2->framePoses[frame2][boneId];
// Blend the transforms
Transform blended;
blended.translation = Vector3Lerp(anim1Transform->translation, anim2Transform->translation, boneBlendFactor);
blended.rotation = QuaternionSlerp(anim1Transform->rotation, anim2Transform->rotation, boneBlendFactor);
blended.scale = Vector3Lerp(anim1Transform->scale, anim2Transform->scale, boneBlendFactor);
// Convert bind pose to matrix
Matrix bindMatrix = MatrixMultiply(MatrixMultiply(
MatrixScale(bindTransform->scale.x, bindTransform->scale.y, bindTransform->scale.z),
QuaternionToMatrix(bindTransform->rotation)),
MatrixTranslate(bindTransform->translation.x, bindTransform->translation.y, bindTransform->translation.z));
// Convert blended transform to matrix
Matrix blendedMatrix = MatrixMultiply(MatrixMultiply(
MatrixScale(blended.scale.x, blended.scale.y, blended.scale.z),
QuaternionToMatrix(blended.rotation)),
MatrixTranslate(blended.translation.x, blended.translation.y, blended.translation.z));
// Calculate final bone matrix (similar to UpdateModelAnimationBones)
model->meshes[firstMeshWithBones].boneMatrices[boneId] = MatrixMultiply(MatrixInvert(bindMatrix), blendedMatrix);
}
// Copy bone matrices to remaining meshes
for (int i = firstMeshWithBones + 1; i < model->meshCount; i++)
{
if (model->meshes[i].boneMatrices)
{
memcpy(model->meshes[i].boneMatrices,
model->meshes[firstMeshWithBones].boneMatrices,
model->meshes[i].boneCount*sizeof(model->meshes[i].boneMatrices[0]));
}
}
}

View file

@ -16,6 +16,7 @@
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#define WORLD_SIZE 8 // Size of our voxel world (8x8x8 cubes)
@ -32,7 +33,7 @@ int main(void)
InitWindow(screenWidth, screenHeight, "raylib [models] example - basic voxel");
DisableCursor(); // Lock mouse to window center
DisableCursor(); // Lock mouse to window center
// Define the camera to look into our 3d world (first person)
Camera3D camera = { 0 };
@ -59,7 +60,7 @@ int main(void)
}
}
}
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
@ -74,7 +75,7 @@ int main(void)
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
{
// Cast a ray from the screen center (where crosshair would be)
Vector2 screenCenter = { screenWidth/2.0f, screenHeight/2.0f };
Vector2 screenCenter = { GetScreenWidth()/2.0f, GetScreenHeight()/2.0f };
Ray ray = GetMouseRay(screenCenter, camera);
// Check ray collision with all voxels
@ -132,8 +133,11 @@ int main(void)
}
}
}
EndMode3D();
// Draw reference point for raycasting to delete blocks
DrawCircle(GetRenderWidth()/2, GetScreenHeight()/2, 4, RED);
DrawText("Left-click a voxel to remove it!", 10, 10, 20, DARKGRAY);
DrawText("WASD to move, mouse to look around", 10, 35, 10, GRAY);
@ -145,6 +149,7 @@ int main(void)
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModel(cubeModel);
CloseWindow();
//--------------------------------------------------------------------------------------

Some files were not shown because too many files have changed in this diff Show more