diff --git a/.github/workflows/webassembly.yml b/.github/workflows/webassembly.yml index 0e815a81c..de35d0ea4 100644 --- a/.github/workflows/webassembly.yml +++ b/.github/workflows/webassembly.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@master - name: Setup emsdk - uses: mymindstorm/setup-emsdk@v7 + uses: mymindstorm/setup-emsdk@v9 with: version: 2.0.0 actions-cache-folder: 'emsdk-cache' diff --git a/examples/Makefile.Web b/examples/Makefile.Web index b9e00ea5d..4aaf54a12 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -599,6 +599,7 @@ core/core_vr_simulator: core/core_vr_simulator.c --preload-file core/resources/distortion100.fs@resources/distortion100.fs # NOTE: To use multi-threading raylib must be compiled with multi-theading support (-s USE_PTHREADS=1) +# WARNING: For security reasons multi-threading is not supported on browsers, it requires cross-origin isolation (Oct.2021) core/core_loading_thread: core/core_loading_thread.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -s USE_PTHREADS=1 @@ -970,8 +971,9 @@ shaders/shaders_hot_reloading: shaders/shaders_hot_reloading.c shaders/shaders_mesh_instancing: shaders/shaders_mesh_instancing.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ - --preload-file shaders/resources/shaders/glsl100/lighting.fs@resources/shaders/glsl100/lighting.fs \ - --preload-file shaders/resources/shaders/glsl100/base_lighting_instanced.vs@resources/shaders/glsl100/base_lighting_instanced.vs + --preload-file shaders/resources/shaders/glsl100/base_lighting_instanced.vs@resources/shaders/glsl100/base_lighting_instanced.vs \ + --preload-file shaders/resources/shaders/glsl100/lighting.fs@resources/shaders/glsl100/lighting.fs + shaders/shaders_multi_sample2d: shaders/shaders_multi_sample2d.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ @@ -1005,21 +1007,20 @@ audio/audio_multichannel_sound: audio/audio_multichannel_sound.c --preload-file audio/resources/target.ogg@resources/target.ogg # Compile PHYSICS examples -# NOTE: To use multi-threading raylib must be compiled with multi-theading support (-s USE_PTHREADS=1) physics/physics_demo: physics/physics_demo.c - $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -static -lpthread -D$(PLATFORM) -s USE_PTHREADS=1 + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -DPHYSAC_AVOID_TIMMING_SYSTEM physics/physics_friction: physics/physics_friction.c - $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -static -lpthread -D$(PLATFORM) -s USE_PTHREADS=1 + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -DPHYSAC_AVOID_TIMMING_SYSTEM physics/physics_movement: physics/physics_movement.c - $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -static -lpthread -D$(PLATFORM) -s USE_PTHREADS=1 + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -DPHYSAC_AVOID_TIMMING_SYSTEM physics/physics_restitution: physics/physics_restitution.c - $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -static -lpthread -D$(PLATFORM) -s USE_PTHREADS=1 + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -DPHYSAC_AVOID_TIMMING_SYSTEM physics/physics_shatter: physics/physics_shatter.c - $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -static -lpthread -D$(PLATFORM) -s USE_PTHREADS=1 + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -DPHYSAC_AVOID_TIMMING_SYSTEM # Clean everything diff --git a/examples/core/core_input_gamepad.c b/examples/core/core_input_gamepad.c index 3595329b2..7da5b94e8 100644 --- a/examples/core/core_input_gamepad.c +++ b/examples/core/core_input_gamepad.c @@ -62,7 +62,7 @@ int main(void) { DrawText(TextFormat("GP1: %s", GetGamepadName(0)), 10, 10, 10, BLACK); - if (IsGamepadName(0, XBOX360_NAME_ID) || IsGamepadName(0, XBOX360_LEGACY_NAME_ID)) + if (TextIsEqual(GetGamepadName(0), XBOX360_NAME_ID) || TextIsEqual(GetGamepadName(0), XBOX360_LEGACY_NAME_ID)) { DrawTexture(texXboxPad, 0, 0, DARKGRAY); @@ -110,7 +110,7 @@ int main(void) //DrawText(TextFormat("Xbox axis LT: %02.02f", GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_TRIGGER)), 10, 40, 10, BLACK); //DrawText(TextFormat("Xbox axis RT: %02.02f", GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_TRIGGER)), 10, 60, 10, BLACK); } - else if (IsGamepadName(0, PS3_NAME_ID)) + else if (TextIsEqual(GetGamepadName(0), PS3_NAME_ID)) { DrawTexture(texPs3Pad, 0, 0, DARKGRAY); diff --git a/examples/core/core_input_multitouch.c b/examples/core/core_input_multitouch.c index 32408a3b1..ef15a9663 100644 --- a/examples/core/core_input_multitouch.c +++ b/examples/core/core_input_multitouch.c @@ -24,11 +24,7 @@ int main(void) InitWindow(screenWidth, screenHeight, "raylib [core] example - input multitouch"); - Vector2 ballPosition = { -100.0f, -100.0f }; - Color ballColor = BEIGE; - - int touchCounter = 0; - Vector2 touchPosition = { 0 }; + Vector2 touchPositions[MAX_TOUCH_POINTS] = { 0 }; SetTargetFPS(60); // Set our game to run at 60 frames-per-second //--------------------------------------------------------------------------------------- @@ -38,19 +34,8 @@ int main(void) { // Update //---------------------------------------------------------------------------------- - ballPosition = GetMousePosition(); - - ballColor = BEIGE; - - if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) ballColor = MAROON; - if (IsMouseButtonDown(MOUSE_BUTTON_MIDDLE)) ballColor = LIME; - if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) ballColor = DARKBLUE; - - if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) touchCounter = 10; - if (IsMouseButtonPressed(MOUSE_BUTTON_MIDDLE)) touchCounter = 10; - if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT)) touchCounter = 10; - - if (touchCounter > 0) touchCounter--; + // Get multiple touchpoints + for (int i = 0; i < MAX_TOUCH_POINTS; ++i) touchPositions[i] = GetTouchPosition(i); //---------------------------------------------------------------------------------- // Draw @@ -58,25 +43,19 @@ int main(void) BeginDrawing(); ClearBackground(RAYWHITE); - - // Multitouch + for (int i = 0; i < MAX_TOUCH_POINTS; ++i) { - touchPosition = GetTouchPosition(i); // Get the touch point - - if ((touchPosition.x >= 0) && (touchPosition.y >= 0)) // Make sure point is not (-1,-1) as this means there is no touch for it + // Make sure point is not (0, 0) as this means there is no touch for it + if ((touchPositions[i].x > 0) && (touchPositions[i].y > 0)) { // Draw circle and touch index number - DrawCircleV(touchPosition, 34, ORANGE); - DrawText(TextFormat("%d", i), (int)touchPosition.x - 10, (int)touchPosition.y - 70, 40, BLACK); + DrawCircleV(touchPositions[i], 34, ORANGE); + DrawText(TextFormat("%d", i), (int)touchPositions[i].x - 10, (int)touchPositions[i].y - 70, 40, BLACK); } } - // Draw the normal mouse location - DrawCircleV(ballPosition, 30 + (touchCounter*3.0f), ballColor); - - DrawText("move ball with mouse and click mouse button to change color", 10, 10, 20, DARKGRAY); - DrawText("touch the screen at multiple locations to get multiple balls", 10, 30, 20, DARKGRAY); + DrawText("touch the screen at multiple locations to get multiple balls", 10, 10, 20, DARKGRAY); EndDrawing(); //---------------------------------------------------------------------------------- diff --git a/examples/core/resources/distortion100.fs b/examples/core/resources/distortion100.fs index 112cbcb5c..f72c68978 100644 --- a/examples/core/resources/distortion100.fs +++ b/examples/core/resources/distortion100.fs @@ -17,7 +17,7 @@ uniform vec2 leftScreenCenter; uniform vec2 rightScreenCenter; uniform vec2 scale; uniform vec2 scaleIn; -uniform vec4 hmdWarpParam; +uniform vec4 deviceWarpParam; uniform vec4 chromaAbParam; void main() @@ -27,7 +27,7 @@ void main() vec2 screenCenter = fragTexCoord.x < 0.5? leftScreenCenter : rightScreenCenter; vec2 theta = (fragTexCoord - lensCenter)*scaleIn; float rSq = theta.x*theta.x + theta.y*theta.y; - vec2 theta1 = theta*(hmdWarpParam.x + hmdWarpParam.y*rSq + hmdWarpParam.z*rSq*rSq + hmdWarpParam.w*rSq*rSq*rSq); + vec2 theta1 = theta*(deviceWarpParam.x + deviceWarpParam.y*rSq + deviceWarpParam.z*rSq*rSq + deviceWarpParam.w*rSq*rSq*rSq); vec2 thetaBlue = theta1*(chromaAbParam.z + chromaAbParam.w*rSq); vec2 tcBlue = lensCenter + scale*thetaBlue; diff --git a/examples/core/resources/distortion330.fs b/examples/core/resources/distortion330.fs index 15d03ccf6..97044c458 100644 --- a/examples/core/resources/distortion330.fs +++ b/examples/core/resources/distortion330.fs @@ -18,7 +18,7 @@ uniform vec2 leftScreenCenter = vec2(0.25, 0.5); uniform vec2 rightScreenCenter = vec2(0.75, 0.5); uniform vec2 scale = vec2(0.25, 0.45); uniform vec2 scaleIn = vec2(4, 2.2222); -uniform vec4 hmdWarpParam = vec4(1, 0.22, 0.24, 0); +uniform vec4 deviceWarpParam = vec4(1, 0.22, 0.24, 0); uniform vec4 chromaAbParam = vec4(0.996, -0.004, 1.014, 0.0); void main() @@ -28,7 +28,7 @@ void main() vec2 screenCenter = fragTexCoord.x < 0.5? leftScreenCenter : rightScreenCenter; vec2 theta = (fragTexCoord - lensCenter)*scaleIn; float rSq = theta.x*theta.x + theta.y*theta.y; - vec2 theta1 = theta*(hmdWarpParam.x + hmdWarpParam.y*rSq + hmdWarpParam.z*rSq*rSq + hmdWarpParam.w*rSq*rSq*rSq); + vec2 theta1 = theta*(deviceWarpParam.x + deviceWarpParam.y*rSq + deviceWarpParam.z*rSq*rSq + deviceWarpParam.w*rSq*rSq*rSq); vec2 thetaBlue = theta1*(chromaAbParam.z + chromaAbParam.w*rSq); vec2 tcBlue = lensCenter + scale*thetaBlue; diff --git a/examples/models/resources/models/gltf/GearboxAssy.glb b/examples/models/resources/models/gltf/GearboxAssy.glb deleted file mode 100644 index 78cdad623..000000000 Binary files a/examples/models/resources/models/gltf/GearboxAssy.glb and /dev/null differ diff --git a/projects/VS2019/examples/models_gltf_animation.vcxproj b/projects/VS2019/examples/models_gltf_animation.vcxproj deleted file mode 100644 index 96e07de5d..000000000 --- a/projects/VS2019/examples/models_gltf_animation.vcxproj +++ /dev/null @@ -1,387 +0,0 @@ - - - - - Debug.DLL - Win32 - - - Debug.DLL - x64 - - - Debug - Win32 - - - Debug - x64 - - - Release.DLL - Win32 - - - Release.DLL - x64 - - - Release - Win32 - - - Release - x64 - - - - {FADC31C3-09AA-4DB4-A289-153482D10C09} - Win32Proj - models_gltf_animation - 10.0 - models_gltf_animation - - - - Application - true - $(DefaultPlatformToolset) - Unicode - - - Application - true - $(DefaultPlatformToolset) - Unicode - - - Application - true - $(DefaultPlatformToolset) - Unicode - - - Application - true - $(DefaultPlatformToolset) - Unicode - - - Application - false - $(DefaultPlatformToolset) - true - Unicode - - - Application - false - $(DefaultPlatformToolset) - true - Unicode - - - Application - false - $(DefaultPlatformToolset) - true - Unicode - - - Application - false - $(DefaultPlatformToolset) - true - Unicode - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - true - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - true - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - true - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - false - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - false - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - false - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - false - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - $(SolutionDir)..\..\examples\models - WindowsLocalDebugger - - - $(SolutionDir)..\..\examples\models - WindowsLocalDebugger - - - $(SolutionDir)..\..\examples\models - WindowsLocalDebugger - - - $(SolutionDir)..\..\examples\models - WindowsLocalDebugger - - - $(SolutionDir)..\..\examples\models - WindowsLocalDebugger - - - $(SolutionDir)..\..\examples\models - WindowsLocalDebugger - - - $(SolutionDir)..\..\examples\models - WindowsLocalDebugger - - - $(SolutionDir)..\..\examples\models - WindowsLocalDebugger - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) - CompileAsC - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - - - Console - true - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) - CompileAsC - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - /FS %(AdditionalOptions) - - - Console - true - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) - CompileAsC - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - - - Console - true - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" - Copy Debug DLL to output directory - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) - CompileAsC - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - - - Console - true - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" - Copy Debug DLL to output directory - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - CompileAsC - true - - - Console - true - true - true - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - CompileAsC - true - - - Console - true - true - true - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - CompileAsC - true - - - Console - true - true - true - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - - - xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" - - - Copy Release DLL to output directory - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - CompileAsC - true - - - Console - true - true - true - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - - - xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" - - - Copy Release DLL to output directory - - - - - - - - {e89d61ac-55de-4482-afd4-df7242ebc859} - - - - - - \ No newline at end of file diff --git a/projects/VS2019/examples/models_gltf_model.vcxproj b/projects/VS2019/examples/models_loading_gltf.vcxproj similarity index 99% rename from projects/VS2019/examples/models_gltf_model.vcxproj rename to projects/VS2019/examples/models_loading_gltf.vcxproj index 92c3ba914..141fb9423 100644 --- a/projects/VS2019/examples/models_gltf_model.vcxproj +++ b/projects/VS2019/examples/models_loading_gltf.vcxproj @@ -37,9 +37,9 @@ {F5FC9279-DE63-4EF3-B31F-CFCEF9B11F71} Win32Proj - models_gltf_model + models_loading_gltf 10.0 - models_gltf_model + models_loading_gltf @@ -374,7 +374,7 @@ - + diff --git a/projects/VS2019/examples/models_loading_vox.vcxproj b/projects/VS2019/examples/models_loading_vox.vcxproj index 420e952ab..d834b27fc 100644 --- a/projects/VS2019/examples/models_loading_vox.vcxproj +++ b/projects/VS2019/examples/models_loading_vox.vcxproj @@ -37,7 +37,7 @@ {2F1B955B-275E-4D8E-8864-06FEC44D7912} Win32Proj - models_mesh_magicavoxel_loading + models_loading_vox 10.0 models_loading_vox @@ -373,14 +373,14 @@ Copy Release DLL to output directory + + + {e89d61ac-55de-4482-afd4-df7242ebc859} - - - diff --git a/projects/VS2019/examples/models_material_pbr.vcxproj b/projects/VS2019/examples/models_material_pbr.vcxproj deleted file mode 100644 index 56c21de52..000000000 --- a/projects/VS2019/examples/models_material_pbr.vcxproj +++ /dev/null @@ -1,387 +0,0 @@ - - - - - Debug.DLL - Win32 - - - Debug.DLL - x64 - - - Debug - Win32 - - - Debug - x64 - - - Release.DLL - Win32 - - - Release.DLL - x64 - - - Release - Win32 - - - Release - x64 - - - - {3A6C48C6-80AB-456F-A3A5-969930958971} - Win32Proj - models_material_pbr - 10.0 - models_material_pbr - - - - Application - true - $(DefaultPlatformToolset) - Unicode - - - Application - true - $(DefaultPlatformToolset) - Unicode - - - Application - true - $(DefaultPlatformToolset) - Unicode - - - Application - true - $(DefaultPlatformToolset) - Unicode - - - Application - false - $(DefaultPlatformToolset) - true - Unicode - - - Application - false - $(DefaultPlatformToolset) - true - Unicode - - - Application - false - $(DefaultPlatformToolset) - true - Unicode - - - Application - false - $(DefaultPlatformToolset) - true - Unicode - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - true - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - true - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - true - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - false - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - false - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - false - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - false - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - $(SolutionDir)..\..\examples\models - WindowsLocalDebugger - - - $(SolutionDir)..\..\examples\models - WindowsLocalDebugger - - - $(SolutionDir)..\..\examples\models - WindowsLocalDebugger - - - $(SolutionDir)..\..\examples\models - WindowsLocalDebugger - - - $(SolutionDir)..\..\examples\models - WindowsLocalDebugger - - - $(SolutionDir)..\..\examples\models - WindowsLocalDebugger - - - $(SolutionDir)..\..\examples\models - WindowsLocalDebugger - - - $(SolutionDir)..\..\examples\models - WindowsLocalDebugger - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) - CompileAsC - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - - - Console - true - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) - CompileAsC - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - /FS %(AdditionalOptions) - - - Console - true - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) - CompileAsC - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - - - Console - true - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" - Copy Debug DLL to output directory - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) - CompileAsC - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - - - Console - true - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" - Copy Debug DLL to output directory - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - CompileAsC - true - - - Console - true - true - true - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - CompileAsC - true - - - Console - true - true - true - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - CompileAsC - true - - - Console - true - true - true - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - - - xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" - - - Copy Release DLL to output directory - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - CompileAsC - true - - - Console - true - true - true - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - - - xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" - - - Copy Release DLL to output directory - - - - - - - - {e89d61ac-55de-4482-afd4-df7242ebc859} - - - - - - \ No newline at end of file diff --git a/projects/VS2019/raylib.sln b/projects/VS2019/raylib.sln index 696d66159..9e26bbb23 100644 --- a/projects/VS2019/raylib.sln +++ b/projects/VS2019/raylib.sln @@ -271,6 +271,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_split_screen", "exampl EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_loading_vox", "examples\models_loading_vox.vcxproj", "{2F1B955B-275E-4D8E-8864-06FEC44D7912}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_loading_gltf", "examples\models_loading_gltf.vcxproj", "{F5FC9279-DE63-4EF3-B31F-CFCEF9B11F71}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug.DLL|x64 = Debug.DLL|x64 @@ -2247,6 +2249,22 @@ Global {2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release|x64.Build.0 = Release|x64 {2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release|x86.ActiveCfg = Release|Win32 {2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release|x86.Build.0 = Release|Win32 + {F5FC9279-DE63-4EF3-B31F-CFCEF9B11F71}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {F5FC9279-DE63-4EF3-B31F-CFCEF9B11F71}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {F5FC9279-DE63-4EF3-B31F-CFCEF9B11F71}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {F5FC9279-DE63-4EF3-B31F-CFCEF9B11F71}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {F5FC9279-DE63-4EF3-B31F-CFCEF9B11F71}.Debug|x64.ActiveCfg = Debug|x64 + {F5FC9279-DE63-4EF3-B31F-CFCEF9B11F71}.Debug|x64.Build.0 = Debug|x64 + {F5FC9279-DE63-4EF3-B31F-CFCEF9B11F71}.Debug|x86.ActiveCfg = Debug|Win32 + {F5FC9279-DE63-4EF3-B31F-CFCEF9B11F71}.Debug|x86.Build.0 = Debug|Win32 + {F5FC9279-DE63-4EF3-B31F-CFCEF9B11F71}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {F5FC9279-DE63-4EF3-B31F-CFCEF9B11F71}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {F5FC9279-DE63-4EF3-B31F-CFCEF9B11F71}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {F5FC9279-DE63-4EF3-B31F-CFCEF9B11F71}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {F5FC9279-DE63-4EF3-B31F-CFCEF9B11F71}.Release|x64.ActiveCfg = Release|x64 + {F5FC9279-DE63-4EF3-B31F-CFCEF9B11F71}.Release|x64.Build.0 = Release|x64 + {F5FC9279-DE63-4EF3-B31F-CFCEF9B11F71}.Release|x86.ActiveCfg = Release|Win32 + {F5FC9279-DE63-4EF3-B31F-CFCEF9B11F71}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -2384,6 +2402,7 @@ Global {C8765523-58F8-4C8E-9914-693396F6F0FF} = {E9D708A5-9C1F-4B84-A795-C5F191801762} {946A1700-C7AA-46F0-AEF2-67C98B5722AC} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} {2F1B955B-275E-4D8E-8864-06FEC44D7912} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C} + {F5FC9279-DE63-4EF3-B31F-CFCEF9B11F71} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29} diff --git a/projects/VS2019/raylib/raylib.vcxproj b/projects/VS2019/raylib/raylib.vcxproj index 51a3c4d8e..d5b2e2322 100644 --- a/projects/VS2019/raylib/raylib.vcxproj +++ b/projects/VS2019/raylib/raylib.vcxproj @@ -312,6 +312,7 @@ + diff --git a/src/Makefile b/src/Makefile index 62b392abf..0d603771b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -581,18 +581,19 @@ raudio.o : raudio.c raylib.h # Compile raygui module # NOTE: raygui header should be distributed with raylib.h -raygui.o : raygui.c raygui.h gui_textbox_extended.h ricons.h +raygui.o : raygui.c $(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM) -DRAYGUI_IMPLEMENTATION raygui.c: - echo '#define RAYGUI_IMPLEMENTATION' > raygui.c - echo '#include "$(RAYLIB_MODULE_RAYGUI_PATH)/raygui.h"' >> raygui.c + echo #define RAYGUI_IMPLEMENTATION > raygui.c + echo #include "$(RAYLIB_MODULE_RAYGUI_PATH)/raygui.h" >> raygui.c # Compile physac module # NOTE: physac header should be distributed with raylib.h -physac.o : physac.c physac.h - @echo #define PHYSAC_IMPLEMENTATION > physac.c - @echo #include "$(RAYLIB_MODULE_PHYSAC_PATH)/physac.h" > physac.c +physac.o : physac.c $(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM) -DPHYSAC_IMPLEMENTATION +physac.c: + @echo #define PHYSAC_IMPLEMENTATION > physac.c + @echo #include "$(RAYLIB_MODULE_PHYSAC_PATH)/physac.h" >> physac.c # Compile android_native_app_glue module android_native_app_glue.o : $(NATIVE_APP_GLUE)/android_native_app_glue.c diff --git a/src/raylib.h b/src/raylib.h index 9f6ce25d6..df21c126a 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -13,7 +13,7 @@ * - Outstanding texture formats support, including compressed formats (DXT, ETC, ASTC) * - Full 3d support for 3d Shapes, Models, Billboards, Heightmaps and more! * - Flexible Materials system, supporting classic maps and PBR maps -* - Animated 3D models supported (skeletal bones animation) (IQM, glTF) +* - Animated 3D models supported (skeletal bones animation) (IQM) * - Shaders support, including Model shaders and Postprocessing shaders * - Powerful math module for Vector, Matrix and Quaternion operations: [raymath] * - Audio loading and playing with streaming support (WAV, OGG, MP3, FLAC, XM, MOD) @@ -1079,7 +1079,6 @@ RLAPI int GetCharPressed(void); // Get char presse // Input-related functions: gamepads RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available -RLAPI bool IsGamepadName(int gamepad, const char *name); // Check gamepad name (if available) RLAPI const char *GetGamepadName(int gamepad); // Get gamepad internal name id RLAPI bool IsGamepadButtonPressed(int gamepad, int button); // Check if a gamepad button has been pressed once RLAPI bool IsGamepadButtonDown(int gamepad, int button); // Check if a gamepad button is being pressed diff --git a/src/rcore.c b/src/rcore.c index 9ab34e158..642a360e2 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -440,7 +440,8 @@ typedef struct CoreData { float currentWheelMove; // Registers current mouse wheel variation float previousWheelMove; // Registers previous mouse wheel variation #if defined(PLATFORM_RPI) || defined(PLATFORM_DRM) - char currentButtonStateEvdev[MAX_MOUSE_BUTTONS]; // Holds the new mouse state for the next polling event to grab (Can't be written directly due to multithreading, app could miss the update) + // NOTE: currentButtonState[] can't be written directly due to multithreading, app could miss the update + char currentButtonStateEvdev[MAX_MOUSE_BUTTONS]; // Holds the new mouse state for the next polling event to grab #endif } Mouse; struct { @@ -454,13 +455,13 @@ typedef struct CoreData { int lastButtonPressed; // Register last gamepad button pressed int axisCount; // Register number of available gamepad axis bool ready[MAX_GAMEPADS]; // Flag to know if gamepad is ready + char name[MAX_GAMEPADS][64]; // Gamepad name holder char currentButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Current gamepad buttons state char previousButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Previous gamepad buttons state float axisState[MAX_GAMEPADS][MAX_GAMEPAD_AXIS]; // Gamepad axis state -#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM) || defined(PLATFORM_WEB) +#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM) pthread_t threadId; // Gamepad reading thread id int streamId[MAX_GAMEPADS]; // Gamepad device file descriptor - char name[MAX_GAMEPADS][64]; // Gamepad name holder #endif } Gamepad; } Input; @@ -3375,18 +3376,6 @@ bool IsGamepadAvailable(int gamepad) return result; } -// Check gamepad name (if available) -bool IsGamepadName(int gamepad, const char *name) -{ - bool result = false; - const char *currentName = NULL; - - if (CORE.Input.Gamepad.ready[gamepad]) currentName = GetGamepadName(gamepad); - if ((name != NULL) && (currentName != NULL)) result = (strcmp(name, currentName) == 0); - - return result; -} - // Get gamepad internal name id const char *GetGamepadName(int gamepad) { @@ -3876,7 +3865,7 @@ static bool InitGraphicsDevice(int width, int height) #if defined(PLATFORM_DESKTOP) // NOTE: GLFW 3.4+ defers initialization of the Joystick subsystem on the first call to any Joystick related functions. - // Forcing this initialization here avoids doing it on `PollInputEvents` called by `EndDrawing` after first frame has been just drawn. + // Forcing this initialization here avoids doing it on PollInputEvents() called by EndDrawing() after first frame has been just drawn. // The initialization will still happen and possible delays still occur, but before the window is shown, which is a nicer experience. // REF: https://github.com/raysan5/raylib/issues/1554 if (MAX_GAMEPADS > 0) glfwSetJoystickCallback(NULL); @@ -4765,6 +4754,11 @@ void PollInputEvents(void) // Register previous touch states for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.previousTouchState[i] = CORE.Input.Touch.currentTouchState[i]; + + // Reset touch positions + // TODO: It resets on PLATFORM_WEB the mouse position and not filled again until a move-event, + // so, if mouse is not moved it returns a (0, 0) position... this behaviour should be reviewed! + //for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.position[i] = (Vector2){ 0, 0 }; #if defined(PLATFORM_DESKTOP) // Check if gamepads are ready diff --git a/src/rmodels.c b/src/rmodels.c index bb07412c3..8c68a0267 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -4494,82 +4494,412 @@ static ModelAnimation* LoadModelAnimationsIQM(const char *fileName, unsigned int #endif #if defined(SUPPORT_FILEFORMAT_GLTF) -// LoadGLTF loads in model data from given filename, supporting both .gltf and .glb +// Load image from different glTF provided methods (uri, path, buffer_view) +static Image LoadImageFromCgltfImage(cgltf_image *cgltfImage, const char *texPath) +{ + Image image = { 0 }; + + if (cgltfImage->uri != NULL) // Check if image data is provided as a uri (base64 or path) + { + if ((strlen(cgltfImage->uri) > 5) && + (cgltfImage->uri[0] == 'd') && + (cgltfImage->uri[1] == 'a') && + (cgltfImage->uri[2] == 't') && + (cgltfImage->uri[3] == 'a') && + (cgltfImage->uri[4] == ':')) // Check if image is provided as base64 text data + { + // Data URI Format: data:;base64, + + // Find the comma + int i = 0; + while ((cgltfImage->uri[i] != ',') && (cgltfImage->uri[i] != 0)) i++; + + if (cgltfImage->uri[i] == 0) TRACELOG(LOG_WARNING, "IMAGE: glTF data URI is not a valid image"); + else + { + int base64Size = strlen(cgltfImage->uri + i + 1); + int outSize = 3*(base64Size/4); // TODO: Consider padding (-numberOfPaddingCharacters) + char *data = NULL; + + cgltf_options options = { 0 }; + cgltf_result result = cgltf_load_buffer_base64(&options, outSize, cgltfImage->uri + i + 1, &data); + + if (result == cgltf_result_success) + { + image = LoadImageFromMemory(".png", data, outSize); + cgltf_free(data); + } + } + } + else // Check if image is provided as image path + { + image = LoadImage(TextFormat("%s/%s", texPath, cgltfImage->uri)); + } + } + else if (cgltfImage->buffer_view->buffer->data != NULL) // Check if image is provided as data buffer + { + unsigned char *data = RL_MALLOC(cgltfImage->buffer_view->size); + int offset = (int)cgltfImage->buffer_view->offset; + int stride = (int)cgltfImage->buffer_view->stride? (int)cgltfImage->buffer_view->stride : 1; + + // Copy buffer data to memory for loading + for (unsigned int i = 0; i < cgltfImage->buffer_view->size; i++) + { + data[i] = ((unsigned char *)cgltfImage->buffer_view->buffer->data)[offset]; + offset += stride; + } + + // Check mime_type for image: (cgltfImage->mime_type == "image\\/png") + if (strcmp(cgltfImage->mime_type, "image\\/png") == 0) image = LoadImageFromMemory(".png", data, (int)cgltfImage->buffer_view->size); + else if (strcmp(cgltfImage->mime_type, "image\\/jpeg") == 0) image = LoadImageFromMemory(".jpg", data, (int)cgltfImage->buffer_view->size); + else TRACELOG(LOG_WARNING, "MODEL: glTF image data MIME type not recognized", TextFormat("%s/%s", texPath, cgltfImage->uri)); + + RL_FREE(data); + } + + return image; +} + +// Load glTF file into model struct, .gltf and .glb supported static Model LoadGLTF(const char *fileName) { - /*********************************************************************************** + /********************************************************************************************* - Function implemented by Wilhem Barbier(@wbrbr), with modifications by Tyler Bezera(@gamerfiend) and Hristo Stamenov(@object71) + Function implemented by Wilhem Barbier(@wbrbr), with modifications by Tyler Bezera(@gamerfiend) + Reviewed by Ramon Santamaria (@raysan5) - Features: + FEATURES: - Supports .gltf and .glb files - Supports embedded (base64) or external textures - - Loads all raylib supported material textures, values and colors - - Supports multiple mesh per model and multiple primitives per model + - Supports PBR metallic/roughness flow, loads material textures, values and colors + PBR specular/glossiness flow and extended texture flows not supported + - Supports multiple meshes per model (every primitives is loaded as a separate mesh) - Some restrictions (not exhaustive): - - Triangle-only meshes - - Not supported node hierarchies or transforms - - Only supports unsigned short indices (no byte/unsigned int) - - Only supports float for texture coordinates (no byte/unsigned short) + RESTRICTIONS: + - Only triangle meshes supported + - Vertex attibute types and formats supported: + > Vertices (position): vec3: float + > Normals: vec3: float + > Texcoords: vec2: float + > Colors: vec4: u8, u16, f32 (normalized) + > Indices: u16, u32 (truncated to u16) + - Node hierarchies or transforms not supported - *************************************************************************************/ + ***********************************************************************************************/ + + // Macro to simplify attributes loading code + #define LOAD_ATTRIBUTE(accesor, numComp, dataType, dstPtr) \ + { \ + int n = 0; \ + dataType *buffer = (dataType *)accesor->buffer_view->buffer->data + accesor->buffer_view->offset/sizeof(dataType) + accesor->offset/sizeof(dataType); \ + for (unsigned int k = 0; k < accesor->count; k++) \ + {\ + for (int l = 0; l < numComp; l++) \ + {\ + dstPtr[numComp*k + l] = buffer[n + l];\ + }\ + n += (int)(accesor->stride/sizeof(dataType));\ + }\ + } Model model = { 0 }; // glTF file loading - unsigned int fileSize = 0; - unsigned char *fileData = LoadFileData(fileName, &fileSize); + unsigned int dataSize = 0; + unsigned char *fileData = LoadFileData(fileName, &dataSize); if (fileData == NULL) return model; // glTF data loading - cgltf_data *gltfData = NULL; - cgltf_options gltfOptions = { 0 }; // TODO: Define custom allocators/file-accessors - cgltf_result result = cgltf_parse(&gltfOptions, fileData, fileSize, &gltfData); - + cgltf_options options = { 0 }; + cgltf_data *data = NULL; + cgltf_result result = cgltf_parse(&options, fileData, dataSize, &data); + if (result == cgltf_result_success) { - TRACELOG(LOG_INFO, "MODEL: [%s] glTF meshes (%s) count: %i", fileName, (gltfData->file_type == 2)? "glb" : "gltf", gltfData->meshes_count); - TRACELOG(LOG_INFO, "MODEL: [%s] glTF materials (%s) count: %i", fileName, (gltfData->file_type == 2)? "glb" : "gltf", gltfData->materials_count); + if (data->file_type == cgltf_file_type_glb) TRACELOG(LOG_INFO, "MODEL: [%s] Model basic data (glb) loaded successfully", fileName); + else if (data->file_type == cgltf_file_type_gltf) TRACELOG(LOG_INFO, "MODEL: [%s] Model basic data (glTF) loaded successfully", fileName); + else TRACELOG(LOG_WARNING, "MODEL: [%s] Model format not recognized", fileName); - // Read data buffers - result = cgltf_load_buffers(&gltfOptions, gltfData, fileName); // TODO: Not needed, gltfData already contains URIs to buffers for manual loading + TRACELOG(LOG_INFO, " > Meshes count: %i", data->meshes_count); + TRACELOG(LOG_INFO, " > Materials count: %i", data->materials_count); + TRACELOG(LOG_DEBUG, " > Buffers count: %i", data->buffers_count); + TRACELOG(LOG_DEBUG, " > Images count: %i", data->images_count); + TRACELOG(LOG_DEBUG, " > Textures count: %i", data->textures_count); + + // Force reading data buffers (fills buffer_view->buffer->data) + // NOTE: If an uri is defined to base64 data or external path, it's automatically loaded -> TODO: Verify this assumption + result = cgltf_load_buffers(&options, data, fileName); if (result != cgltf_result_success) TRACELOG(LOG_INFO, "MODEL: [%s] Failed to load mesh/material buffers", fileName); - if (gltfData->scenes_count > 1) TRACELOG(LOG_INFO, "MODEL: [%s] Has multiple scenes but only the first one will be loaded", fileName); + int primitivesCount = 0; + // NOTE: We will load every primitive in the glTF as a separate raylib mesh + for (unsigned int i = 0; i < data->meshes_count; i++) primitivesCount += (int)data->meshes[i].primitives_count; - int primitiveCount = 0; - for (unsigned int i = 0; i < gltfData->scene->nodes_count; i++) - { - //GetGLTFPrimitiveCount(gltfData->scene->nodes[i], &primitiveCount); // TODO: Recursive function, really needed? - } - - // Process glTF data and map to model - model.meshCount = primitiveCount; + // Load our model data: meshes and materials + model.meshCount = primitivesCount; model.meshes = RL_CALLOC(model.meshCount, sizeof(Mesh)); - model.materialCount = (int)gltfData->materials_count + 1; - model.materials = RL_MALLOC(model.materialCount*sizeof(Material)); - model.meshMaterial = RL_MALLOC(model.meshCount*sizeof(int)); - model.boneCount = (int)gltfData->nodes_count; - model.bones = RL_CALLOC(model.boneCount, sizeof(BoneInfo)); - model.bindPose = RL_CALLOC(model.boneCount, sizeof(Transform)); + for (int i = 0; i < model.meshCount; i++) model.meshes[i].vboId = (unsigned int*)RL_CALLOC(MAX_MESH_VERTEX_BUFFERS, sizeof(unsigned int)); - //InitGLTFBones(&model, gltfData); - //LoadGLTFMaterial(&model, fileName, gltfData); + // NOTE: We keep an extra slot for default material, in case some mesh requires it + model.materialCount = (int)data->materials_count + 1; + model.materials = RL_CALLOC(model.materialCount, sizeof(Material)); + model.materials[0] = LoadMaterialDefault(); // Load default material (index: 0) - int primitiveIndex = 0; - for (unsigned int i = 0; i < gltfData->scene->nodes_count; i++) + // Load mesh-material indices, by default all meshes are mapped to material index: 0 + model.meshMaterial = RL_CALLOC(model.meshCount, sizeof(int)); + + // Load materials data + for (unsigned int i = 0, j = 1; i < data->materials_count; i++, j++) { - Matrix staticTransform = MatrixIdentity(); - //LoadGLTFNode(gltfData, gltfData->scene->nodes[i], &model, staticTransform, &primitiveIndex, fileName); // TODO: Recursive function, really needed? + model.materials[j] = LoadMaterialDefault(); + const char *texPath = GetDirectoryPath(fileName); + + // Check glTF material flow: PBR metallic/roughness flow + // NOTE: Alternatively, materials can follow PBR specular/glossiness flow + if (data->materials[i].has_pbr_metallic_roughness) + { + // Load base color texture (albedo) + if (data->materials[i].pbr_metallic_roughness.base_color_texture.texture) + { + Image imAlbedo = LoadImageFromCgltfImage(data->materials[i].pbr_metallic_roughness.base_color_texture.texture->image, texPath); + if (imAlbedo.data != NULL) + { + model.materials[j].maps[MATERIAL_MAP_ALBEDO].texture = LoadTextureFromImage(imAlbedo); + UnloadImage(imAlbedo); + } + + // Load base color factor (tint) + model.materials[j].maps[MATERIAL_MAP_ALBEDO].color.r = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[0]*255); + model.materials[j].maps[MATERIAL_MAP_ALBEDO].color.g = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[1]*255); + model.materials[j].maps[MATERIAL_MAP_ALBEDO].color.b = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[2]*255); + model.materials[j].maps[MATERIAL_MAP_ALBEDO].color.a = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[3]*255); + } + + // Load metallic/roughness texture + if (data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.texture) + { + Image imMetallicRoughness = LoadImageFromCgltfImage(data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.texture->image, texPath); + if (imMetallicRoughness.data != NULL) + { + model.materials[j].maps[MATERIAL_MAP_ROUGHNESS].texture = LoadTextureFromImage(imMetallicRoughness); + UnloadImage(imMetallicRoughness); + } + + // Load metallic/roughness material properties + float roughness = data->materials[i].pbr_metallic_roughness.roughness_factor; + model.materials[j].maps[MATERIAL_MAP_ROUGHNESS].value = roughness; + + float metallic = data->materials[i].pbr_metallic_roughness.metallic_factor; + model.materials[j].maps[MATERIAL_MAP_METALNESS].value = metallic; + } + + // Load normal texture + if (data->materials[i].normal_texture.texture) + { + Image imNormal = LoadImageFromCgltfImage(data->materials[i].normal_texture.texture->image, texPath); + if (imNormal.data != NULL) + { + model.materials[j].maps[MATERIAL_MAP_NORMAL].texture = LoadTextureFromImage(imNormal); + UnloadImage(imNormal); + } + } + + // Load ambient occlusion texture + if (data->materials[i].occlusion_texture.texture) + { + Image imOcclusion = LoadImageFromCgltfImage(data->materials[i].occlusion_texture.texture->image, texPath); + if (imOcclusion.data != NULL) + { + model.materials[j].maps[MATERIAL_MAP_OCCLUSION].texture = LoadTextureFromImage(imOcclusion); + UnloadImage(imOcclusion); + } + } + + // Load emissive texture + if (data->materials[i].emissive_texture.texture) + { + Image imEmissive = LoadImageFromCgltfImage(data->materials[i].emissive_texture.texture->image, texPath); + if (imEmissive.data != NULL) + { + model.materials[j].maps[MATERIAL_MAP_EMISSION].texture = LoadTextureFromImage(imEmissive); + UnloadImage(imEmissive); + } + + // Load emissive color factor + model.materials[j].maps[MATERIAL_MAP_EMISSION].color.r = (unsigned char)(data->materials[i].emissive_factor[0]*255); + model.materials[j].maps[MATERIAL_MAP_EMISSION].color.g = (unsigned char)(data->materials[i].emissive_factor[1]*255); + model.materials[j].maps[MATERIAL_MAP_EMISSION].color.b = (unsigned char)(data->materials[i].emissive_factor[2]*255); + model.materials[j].maps[MATERIAL_MAP_EMISSION].color.a = 255; + } + } + + // Other possible materials not supported by raylib pipeline: + // has_clearcoat, has_transmission, has_volume, has_ior, has specular, has_sheen } - cgltf_free(gltfData); + // Load meshes data + for (unsigned int i = 0; i < data->meshes_count; i++) + { + for (unsigned int p = 0, primitiveIndex = 0; p < data->meshes[i].primitives_count; p++) + { + // NOTE: We only support primitives defined by triangles + // Other alternatives: points, lines, line_strip, triangle_strip + if (data->meshes[i].primitives[p].type != cgltf_primitive_type_triangles) continue; + + // NOTE: Attributes data could be provided in several data formats (8, 8u, 16u, 32...), + // Only some formats for each attribute type are supported, read info at the top of this function! + + for (unsigned int j = 0; j < data->meshes[i].primitives[p].attributes_count; j++) + { + // Check the different attributes for every pimitive + if (data->meshes[i].primitives[p].attributes[j].type == cgltf_attribute_type_position) // POSITION + { + cgltf_accessor *attribute = data->meshes[i].primitives[p].attributes[j].data; + + if ((attribute->component_type == cgltf_component_type_r_32f) && (attribute->type == cgltf_type_vec3)) + { + // Init raylib mesh vertices to copy glTF attribute data + model.meshes[primitiveIndex].vertexCount = (int)attribute->count; + model.meshes[primitiveIndex].vertices = RL_MALLOC(attribute->count*3*sizeof(float)); + + // Load 3 components of float data type into mesh.vertices + LOAD_ATTRIBUTE(attribute, 3, float, model.meshes[primitiveIndex].vertices) + } + else TRACELOG(LOG_WARNING, "MODEL: [%s] Vertices attribute data format not supported, use vec3 float", fileName); + } + else if (data->meshes[i].primitives[p].attributes[j].type == cgltf_attribute_type_normal) // NORMAL + { + cgltf_accessor *attribute = data->meshes[i].primitives[p].attributes[j].data; + + if ((attribute->component_type == cgltf_component_type_r_32f) && (attribute->type == cgltf_type_vec3)) + { + // Init raylib mesh normals to copy glTF attribute data + model.meshes[primitiveIndex].normals = RL_MALLOC(attribute->count*3*sizeof(float)); + + // Load 3 components of float data type into mesh.normals + LOAD_ATTRIBUTE(attribute, 3, float, model.meshes[primitiveIndex].normals) + } + else TRACELOG(LOG_WARNING, "MODEL: [%s] Normal attribute data format not supported, use vec3 float", fileName); + } + else if (data->meshes[i].primitives[p].attributes[j].type == cgltf_attribute_type_texcoord) // TEXCOORD_0 + { + cgltf_accessor *attribute = data->meshes[i].primitives[p].attributes[j].data; + + if ((attribute->component_type == cgltf_component_type_r_32f) && (attribute->type == cgltf_type_vec2)) + { + // Init raylib mesh texcoords to copy glTF attribute data + model.meshes[primitiveIndex].texcoords = RL_MALLOC(attribute->count*2*sizeof(float)); + + // Load 3 components of float data type into mesh.texcoords + LOAD_ATTRIBUTE(attribute, 2, float, model.meshes[primitiveIndex].texcoords) + } + else TRACELOG(LOG_WARNING, "MODEL: [%s] Texcoords attribute data format not supported, use vec2 float", fileName); + } + else if (data->meshes[i].primitives[p].attributes[j].type == cgltf_attribute_type_color) // COLOR_0 + { + cgltf_accessor *attribute = data->meshes[i].primitives[p].attributes[j].data; + + if ((attribute->component_type == cgltf_component_type_r_8u) && (attribute->type == cgltf_type_vec4)) + { + // Init raylib mesh color to copy glTF attribute data + model.meshes[primitiveIndex].colors = RL_MALLOC(attribute->count*4*sizeof(unsigned char)); + + // Load 4 components of unsigned char data type into mesh.colors + LOAD_ATTRIBUTE(attribute, 4, unsigned char, model.meshes[primitiveIndex].colors) + } + else if ((attribute->component_type == cgltf_component_type_r_16u) && (attribute->type == cgltf_type_vec4)) + { + // Init raylib mesh color to copy glTF attribute data + model.meshes[primitiveIndex].colors = RL_MALLOC(attribute->count*4*sizeof(unsigned char)); + + // Load data into a temp buffer to be converted to raylib data type + unsigned short *temp = RL_MALLOC(attribute->count*4*sizeof(unsigned short)); + LOAD_ATTRIBUTE(attribute, 4, unsigned short, temp); + + // Convert data to raylib color data type (4 bytes) + for (int c = 0; c < attribute->count*4; c++) model.meshes[primitiveIndex].colors[c] = (unsigned char)(((float)temp[c]/65535.0f)*255.0f); + + RL_FREE(temp); + } + else if ((attribute->component_type == cgltf_component_type_r_32f) && (attribute->type == cgltf_type_vec4)) + { + // Init raylib mesh color to copy glTF attribute data + model.meshes[primitiveIndex].colors = RL_MALLOC(attribute->count*4*sizeof(unsigned char)); + + // Load data into a temp buffer to be converted to raylib data type + float *temp = RL_MALLOC(attribute->count*4*sizeof(float)); + LOAD_ATTRIBUTE(attribute, 4, float, temp); + + // Convert data to raylib color data type (4 bytes), we expect the color data normalized + for (int c = 0; c < attribute->count*4; c++) model.meshes[primitiveIndex].colors[c] = (unsigned char)(temp[c]*255.0f); + + RL_FREE(temp); + } + else TRACELOG(LOG_WARNING, "MODEL: [%s] Color attribute data format not supported", fileName); + } + + // TODO: Additional attributes that could be supported (some related to animations): + // cgltf_attribute_type_tangent, cgltf_attribute_type_joints, cgltf_attribute_type_weights + } + + // Load primitive indices data (if provided) + cgltf_accessor *attribute = data->meshes[i].primitives[p].indices; + + if (attribute != NULL) + { + model.meshes[primitiveIndex].triangleCount = (int)attribute->count/3; + + if (attribute->component_type == cgltf_component_type_r_16u) + { + // Init raylib mesh indices to copy glTF attribute data + model.meshes[primitiveIndex].indices = RL_MALLOC(attribute->count*sizeof(unsigned short)); + + // Load unsigned short data type into mesh.indices + LOAD_ATTRIBUTE(attribute, 1, unsigned short, model.meshes[primitiveIndex].indices) + } + else if (attribute->component_type == cgltf_component_type_r_32u) + { + // Init raylib mesh indices to copy glTF attribute data + model.meshes[primitiveIndex].indices = RL_MALLOC(attribute->count*sizeof(unsigned short)); + + // Load data into a temp buffer to be converted to raylib data type + unsigned int *temp = RL_MALLOC(attribute->count*sizeof(unsigned int)); + LOAD_ATTRIBUTE(attribute, 1, unsigned int, temp); + + // Convert data to raylib indices data type (unsigned short) + for (int d = 0; d < attribute->count; d++) model.meshes[primitiveIndex].indices[d] = (unsigned short)temp[d]; + + TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data converted from u32 to u16, possible loss of data", fileName); + + RL_FREE(temp); + } + else TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data format not supported, use u16", fileName); + } + else model.meshes[primitiveIndex].triangleCount = model.meshes[primitiveIndex].vertexCount/3; // Unindexed mesh + + // Assign to the primitive mesh the corresponding material index + // NOTE: If no material defined, mesh uses the already assigned default material (index: 0) + for (int m = 0; m < data->materials_count; m++) + { + // The primitive actually keeps the pointer to the corresponding material, + // raylib instead assigns to the mesh the by its index, as loaded in model.materials array + // To get the index, we check if material pointers match and we assign the corresponding index, + // skipping index 0, the default material + if (&data->materials[i] == data->meshes[i].primitives[p].material) model.meshMaterial[primitiveIndex] = m + 1; + } + + primitiveIndex++; // Move to next primitive + } + } + + // Free all cgltf loaded data + cgltf_free(data); } else TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load glTF data", fileName); - RL_FREE(fileData); + // WARNING: cgltf requires the file pointer available while reading data + UnloadFileData(fileData); return model; }