Merge branch 'raysan5:master' into master
This commit is contained in:
commit
a1de46c384
18
.github/workflows/build_android.yml
vendored
18
.github/workflows/build_android.yml
vendored
|
|
@ -28,20 +28,20 @@ jobs:
|
||||||
max-parallel: 1
|
max-parallel: 1
|
||||||
matrix:
|
matrix:
|
||||||
ARCH: ["arm64", "x86_64"]
|
ARCH: ["arm64", "x86_64"]
|
||||||
|
|
||||||
env:
|
env:
|
||||||
RELEASE_NAME: raylib-dev_android_api29_${{ matrix.ARCH }}
|
RELEASE_NAME: raylib-dev_android_api29_${{ matrix.ARCH }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@master
|
||||||
|
|
||||||
- name: Setup Release Version
|
- name: Setup Release Version
|
||||||
run: |
|
run: |
|
||||||
echo "RELEASE_NAME=raylib-${{ github.event.release.tag_name }}_android_api29_${{ matrix.ARCH }}" >> $GITHUB_ENV
|
echo "RELEASE_NAME=raylib-${{ github.event.release.tag_name }}_android_api29_${{ matrix.ARCH }}" >> $GITHUB_ENV
|
||||||
shell: bash
|
shell: bash
|
||||||
if: github.event_name == 'release' && github.event.action == 'published'
|
if: github.event_name == 'release' && github.event.action == 'published'
|
||||||
|
|
||||||
- name: Setup Android NDK
|
- name: Setup Android NDK
|
||||||
id: setup-ndk
|
id: setup-ndk
|
||||||
uses: nttld/setup-ndk@v1
|
uses: nttld/setup-ndk@v1
|
||||||
|
|
@ -52,7 +52,7 @@ jobs:
|
||||||
ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
|
ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
|
||||||
|
|
||||||
- name: Setup Environment
|
- name: Setup Environment
|
||||||
run: |
|
run: |
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
mkdir ${{ env.RELEASE_NAME }}
|
mkdir ${{ env.RELEASE_NAME }}
|
||||||
|
|
@ -60,7 +60,7 @@ jobs:
|
||||||
mkdir include
|
mkdir include
|
||||||
mkdir lib
|
mkdir lib
|
||||||
cd ../..
|
cd ../..
|
||||||
|
|
||||||
# Generating static + shared library for 64bit arquitectures and API version 29
|
# Generating static + shared library for 64bit arquitectures and API version 29
|
||||||
- name: Build Library
|
- name: Build Library
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -69,7 +69,7 @@ jobs:
|
||||||
make PLATFORM=PLATFORM_ANDROID ANDROID_ARCH=${{ matrix.ARCH }} ANDROID_API_VERSION=29 ANDROID_NDK=${{ env.ANDROID_NDK_HOME }} RAYLIB_LIBTYPE=SHARED RAYLIB_RELEASE_PATH="../build/${{ env.RELEASE_NAME }}/lib" -B
|
make PLATFORM=PLATFORM_ANDROID ANDROID_ARCH=${{ matrix.ARCH }} ANDROID_API_VERSION=29 ANDROID_NDK=${{ env.ANDROID_NDK_HOME }} RAYLIB_LIBTYPE=SHARED RAYLIB_RELEASE_PATH="../build/${{ env.RELEASE_NAME }}/lib" -B
|
||||||
cd ..
|
cd ..
|
||||||
shell: cmd
|
shell: cmd
|
||||||
|
|
||||||
- name: Generate Artifacts
|
- name: Generate Artifacts
|
||||||
run: |
|
run: |
|
||||||
cp -v ./src/raylib.h ./build/${{ env.RELEASE_NAME }}/include
|
cp -v ./src/raylib.h ./build/${{ env.RELEASE_NAME }}/include
|
||||||
|
|
@ -80,7 +80,7 @@ jobs:
|
||||||
cp -v ./LICENSE ./build/${{ env.RELEASE_NAME }}/LICENSE
|
cp -v ./LICENSE ./build/${{ env.RELEASE_NAME }}/LICENSE
|
||||||
cd build
|
cd build
|
||||||
tar -czvf ${{ env.RELEASE_NAME }}.tar.gz ${{ env.RELEASE_NAME }}
|
tar -czvf ${{ env.RELEASE_NAME }}.tar.gz ${{ env.RELEASE_NAME }}
|
||||||
|
|
||||||
- name: Upload Artifacts
|
- name: Upload Artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
|
|
@ -88,7 +88,7 @@ jobs:
|
||||||
path: |
|
path: |
|
||||||
./build/${{ env.RELEASE_NAME }}
|
./build/${{ env.RELEASE_NAME }}
|
||||||
!./build/${{ env.RELEASE_NAME }}.tar.gz
|
!./build/${{ env.RELEASE_NAME }}.tar.gz
|
||||||
|
|
||||||
- name: Upload Artifact to Release
|
- name: Upload Artifact to Release
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
8
.github/workflows/build_examples_linux.yml
vendored
8
.github/workflows/build_examples_linux.yml
vendored
|
|
@ -23,18 +23,18 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup Environment
|
- name: Setup Environment
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update -qq
|
sudo apt-get update -qq
|
||||||
sudo apt-get install -y --no-install-recommends libglfw3 libglfw3-dev libx11-dev libxcursor-dev libxrandr-dev libxinerama-dev libxi-dev libxext-dev libxfixes-dev libwayland-dev libxkbcommon-dev
|
sudo apt-get install -y --no-install-recommends libglfw3 libglfw3-dev libx11-dev libxcursor-dev libxrandr-dev libxinerama-dev libxi-dev libxext-dev libxfixes-dev libwayland-dev libxkbcommon-dev
|
||||||
|
|
||||||
- name: Build Library
|
- name: Build Library
|
||||||
run: |
|
run: |
|
||||||
cd src
|
cd src
|
||||||
make PLATFORM=PLATFORM_DESKTOP CC=gcc RAYLIB_LIBTYPE=STATIC
|
make PLATFORM=PLATFORM_DESKTOP CC=gcc RAYLIB_LIBTYPE=STATIC
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
- name: Build Examples
|
- name: Build Examples
|
||||||
run: |
|
run: |
|
||||||
cd examples
|
cd examples
|
||||||
|
|
|
||||||
2
.github/workflows/build_examples_windows.yml
vendored
2
.github/workflows/build_examples_windows.yml
vendored
|
|
@ -13,7 +13,7 @@ on:
|
||||||
- 'src/**'
|
- 'src/**'
|
||||||
- 'examples/**'
|
- 'examples/**'
|
||||||
- '.github/workflows/windows_examples.yml'
|
- '.github/workflows/windows_examples.yml'
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
|
|
|
||||||
20
.github/workflows/build_linux.yml
vendored
20
.github/workflows/build_linux.yml
vendored
|
|
@ -42,23 +42,23 @@ jobs:
|
||||||
ARCH_NAME: "arm64"
|
ARCH_NAME: "arm64"
|
||||||
COMPILER_PATH: "/usr/bin"
|
COMPILER_PATH: "/usr/bin"
|
||||||
runner: "ubuntu-24.04-arm"
|
runner: "ubuntu-24.04-arm"
|
||||||
|
|
||||||
runs-on: ${{ matrix.runner }}
|
runs-on: ${{ matrix.runner }}
|
||||||
env:
|
env:
|
||||||
RELEASE_NAME: raylib-dev_linux_${{ matrix.ARCH_NAME }}
|
RELEASE_NAME: raylib-dev_linux_${{ matrix.ARCH_NAME }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@master
|
||||||
|
|
||||||
- name: Setup Release Version
|
- name: Setup Release Version
|
||||||
run: |
|
run: |
|
||||||
echo "RELEASE_NAME=raylib-${{ github.event.release.tag_name }}_linux_${{ matrix.ARCH_NAME }}" >> $GITHUB_ENV
|
echo "RELEASE_NAME=raylib-${{ github.event.release.tag_name }}_linux_${{ matrix.ARCH_NAME }}" >> $GITHUB_ENV
|
||||||
shell: bash
|
shell: bash
|
||||||
if: github.event_name == 'release' && github.event.action == 'published'
|
if: github.event_name == 'release' && github.event.action == 'published'
|
||||||
|
|
||||||
- name: Setup Environment
|
- name: Setup Environment
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update -qq
|
sudo apt-get update -qq
|
||||||
sudo apt-get install -y --no-install-recommends libglfw3 libglfw3-dev libx11-dev libxcursor-dev libxrandr-dev libxinerama-dev libxi-dev libxext-dev libxfixes-dev libwayland-dev libxkbcommon-dev
|
sudo apt-get install -y --no-install-recommends libglfw3 libglfw3-dev libx11-dev libxcursor-dev libxrandr-dev libxinerama-dev libxi-dev libxext-dev libxfixes-dev libwayland-dev libxkbcommon-dev
|
||||||
mkdir build
|
mkdir build
|
||||||
|
|
@ -74,7 +74,7 @@ jobs:
|
||||||
run : |
|
run : |
|
||||||
sudo apt-get install gcc-multilib
|
sudo apt-get install gcc-multilib
|
||||||
if: matrix.bits == 32 && matrix.ARCH == 'i386'
|
if: matrix.bits == 32 && matrix.ARCH == 'i386'
|
||||||
|
|
||||||
# TODO: Support 32bit (i386) static/shared library building
|
# TODO: Support 32bit (i386) static/shared library building
|
||||||
- name: Build Library (32-bit)
|
- name: Build Library (32-bit)
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -91,7 +91,7 @@ jobs:
|
||||||
make PLATFORM=PLATFORM_DESKTOP CC=gcc RAYLIB_LIBTYPE=SHARED RAYLIB_RELEASE_PATH="../build/${{ env.RELEASE_NAME }}/lib" -B
|
make PLATFORM=PLATFORM_DESKTOP CC=gcc RAYLIB_LIBTYPE=SHARED RAYLIB_RELEASE_PATH="../build/${{ env.RELEASE_NAME }}/lib" -B
|
||||||
cd ..
|
cd ..
|
||||||
if: matrix.bits == 64 && matrix.ARCH == 'x86_64'
|
if: matrix.bits == 64 && matrix.ARCH == 'x86_64'
|
||||||
|
|
||||||
- name: Build Library (64-bit ARM)
|
- name: Build Library (64-bit ARM)
|
||||||
run: |
|
run: |
|
||||||
cd src
|
cd src
|
||||||
|
|
@ -99,7 +99,7 @@ jobs:
|
||||||
make PLATFORM=PLATFORM_DESKTOP CC=gcc RAYLIB_LIBTYPE=SHARED RAYLIB_RELEASE_PATH="../build/${{ env.RELEASE_NAME }}/lib" -B
|
make PLATFORM=PLATFORM_DESKTOP CC=gcc RAYLIB_LIBTYPE=SHARED RAYLIB_RELEASE_PATH="../build/${{ env.RELEASE_NAME }}/lib" -B
|
||||||
cd ..
|
cd ..
|
||||||
if: matrix.bits == 64 && matrix.ARCH == 'aarch64'
|
if: matrix.bits == 64 && matrix.ARCH == 'aarch64'
|
||||||
|
|
||||||
- name: Generate Artifacts
|
- name: Generate Artifacts
|
||||||
run: |
|
run: |
|
||||||
cp -v ./src/raylib.h ./build/${{ env.RELEASE_NAME }}/include
|
cp -v ./src/raylib.h ./build/${{ env.RELEASE_NAME }}/include
|
||||||
|
|
@ -110,7 +110,7 @@ jobs:
|
||||||
cp -v ./LICENSE ./build/${{ env.RELEASE_NAME }}/LICENSE
|
cp -v ./LICENSE ./build/${{ env.RELEASE_NAME }}/LICENSE
|
||||||
cd build
|
cd build
|
||||||
tar -czvf ${{ env.RELEASE_NAME }}.tar.gz ${{ env.RELEASE_NAME }}
|
tar -czvf ${{ env.RELEASE_NAME }}.tar.gz ${{ env.RELEASE_NAME }}
|
||||||
|
|
||||||
- name: Upload Artifacts
|
- name: Upload Artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
|
|
@ -118,7 +118,7 @@ jobs:
|
||||||
path: |
|
path: |
|
||||||
./build/${{ env.RELEASE_NAME }}
|
./build/${{ env.RELEASE_NAME }}
|
||||||
!./build/${{ env.RELEASE_NAME }}.tar.gz
|
!./build/${{ env.RELEASE_NAME }}.tar.gz
|
||||||
|
|
||||||
- name: Upload Artifact to Release
|
- name: Upload Artifact to Release
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
30
.github/workflows/build_macos.yml
vendored
30
.github/workflows/build_macos.yml
vendored
|
|
@ -23,14 +23,14 @@ jobs:
|
||||||
permissions:
|
permissions:
|
||||||
contents: write # for actions/upload-release-asset to upload release asset
|
contents: write # for actions/upload-release-asset to upload release asset
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
|
|
||||||
env:
|
env:
|
||||||
RELEASE_NAME: raylib-dev_macos
|
RELEASE_NAME: raylib-dev_macos
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@master
|
||||||
|
|
||||||
- name: Setup Release Version
|
- name: Setup Release Version
|
||||||
run: |
|
run: |
|
||||||
echo "RELEASE_NAME=raylib-${{ github.event.release.tag_name }}_macos" >> $GITHUB_ENV
|
echo "RELEASE_NAME=raylib-${{ github.event.release.tag_name }}_macos" >> $GITHUB_ENV
|
||||||
|
|
@ -38,7 +38,7 @@ jobs:
|
||||||
if: github.event_name == 'release' && github.event.action == 'published'
|
if: github.event_name == 'release' && github.event.action == 'published'
|
||||||
|
|
||||||
- name: Setup Environment
|
- name: Setup Environment
|
||||||
run: |
|
run: |
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
mkdir ${{ env.RELEASE_NAME }}
|
mkdir ${{ env.RELEASE_NAME }}
|
||||||
|
|
@ -46,47 +46,47 @@ jobs:
|
||||||
mkdir include
|
mkdir include
|
||||||
mkdir lib
|
mkdir lib
|
||||||
cd ../..
|
cd ../..
|
||||||
|
|
||||||
# Generating static + shared library, note that i386 architecture is deprecated
|
# Generating static + shared library, note that i386 architecture is deprecated
|
||||||
# Defining GL_SILENCE_DEPRECATION because OpenGL is deprecated on macOS
|
# Defining GL_SILENCE_DEPRECATION because OpenGL is deprecated on macOS
|
||||||
- name: Build Library
|
- name: Build Library
|
||||||
run: |
|
run: |
|
||||||
cd src
|
cd src
|
||||||
clang --version
|
clang --version
|
||||||
|
|
||||||
# Extract version numbers from Makefile
|
# Extract version numbers from Makefile
|
||||||
brew install grep
|
brew install grep
|
||||||
RAYLIB_API_VERSION=`ggrep -Po 'RAYLIB_API_VERSION\s*=\s\K(.*)' Makefile`
|
RAYLIB_API_VERSION=`ggrep -Po 'RAYLIB_API_VERSION\s*=\s\K(.*)' Makefile`
|
||||||
RAYLIB_VERSION=`ggrep -Po 'RAYLIB_VERSION\s*=\s\K(.*)' Makefile`
|
RAYLIB_VERSION=`ggrep -Po 'RAYLIB_VERSION\s*=\s\K(.*)' Makefile`
|
||||||
|
|
||||||
# Build raylib x86_64 static
|
# Build raylib x86_64 static
|
||||||
make PLATFORM=PLATFORM_DESKTOP RAYLIB_LIBTYPE=STATIC CUSTOM_CFLAGS="-target x86_64-apple-macos10.12 -DGL_SILENCE_DEPRECATION"
|
make PLATFORM=PLATFORM_DESKTOP RAYLIB_LIBTYPE=STATIC CUSTOM_CFLAGS="-target x86_64-apple-macos10.12 -DGL_SILENCE_DEPRECATION"
|
||||||
mv libraylib.a /tmp/libraylib_x86_64.a
|
mv libraylib.a /tmp/libraylib_x86_64.a
|
||||||
make clean
|
make clean
|
||||||
|
|
||||||
# Build raylib arm64 static
|
# Build raylib arm64 static
|
||||||
make PLATFORM=PLATFORM_DESKTOP RAYLIB_LIBTYPE=STATIC CUSTOM_CFLAGS="-target arm64-apple-macos11 -DGL_SILENCE_DEPRECATION" -B
|
make PLATFORM=PLATFORM_DESKTOP RAYLIB_LIBTYPE=STATIC CUSTOM_CFLAGS="-target arm64-apple-macos11 -DGL_SILENCE_DEPRECATION" -B
|
||||||
mv libraylib.a /tmp/libraylib_arm64.a
|
mv libraylib.a /tmp/libraylib_arm64.a
|
||||||
make clean
|
make clean
|
||||||
|
|
||||||
# Join x86_64 and arm64 static
|
# Join x86_64 and arm64 static
|
||||||
lipo -create -output ../build/${{ env.RELEASE_NAME }}/lib/libraylib.a /tmp/libraylib_x86_64.a /tmp/libraylib_arm64.a
|
lipo -create -output ../build/${{ env.RELEASE_NAME }}/lib/libraylib.a /tmp/libraylib_x86_64.a /tmp/libraylib_arm64.a
|
||||||
|
|
||||||
# Build raylib x86_64 dynamic
|
# Build raylib x86_64 dynamic
|
||||||
make PLATFORM=PLATFORM_DESKTOP RAYLIB_LIBTYPE=SHARED CUSTOM_CFLAGS="-target x86_64-apple-macos10.12 -DGL_SILENCE_DEPRECATION" CUSTOM_LDFLAGS="-target x86_64-apple-macos10.12" -B
|
make PLATFORM=PLATFORM_DESKTOP RAYLIB_LIBTYPE=SHARED CUSTOM_CFLAGS="-target x86_64-apple-macos10.12 -DGL_SILENCE_DEPRECATION" CUSTOM_LDFLAGS="-target x86_64-apple-macos10.12" -B
|
||||||
mv libraylib.${RAYLIB_VERSION}.dylib /tmp/libraylib_x86_64.${RAYLIB_VERSION}.dylib
|
mv libraylib.${RAYLIB_VERSION}.dylib /tmp/libraylib_x86_64.${RAYLIB_VERSION}.dylib
|
||||||
make clean
|
make clean
|
||||||
|
|
||||||
# Build raylib arm64 dynamic
|
# Build raylib arm64 dynamic
|
||||||
make PLATFORM=PLATFORM_DESKTOP RAYLIB_LIBTYPE=SHARED CUSTOM_CFLAGS="-target arm64-apple-macos11 -DGL_SILENCE_DEPRECATION" CUSTOM_LDFLAGS="-target arm64-apple-macos11" -B
|
make PLATFORM=PLATFORM_DESKTOP RAYLIB_LIBTYPE=SHARED CUSTOM_CFLAGS="-target arm64-apple-macos11 -DGL_SILENCE_DEPRECATION" CUSTOM_LDFLAGS="-target arm64-apple-macos11" -B
|
||||||
mv libraylib.${RAYLIB_VERSION}.dylib /tmp/libraylib_arm64.${RAYLIB_VERSION}.dylib
|
mv libraylib.${RAYLIB_VERSION}.dylib /tmp/libraylib_arm64.${RAYLIB_VERSION}.dylib
|
||||||
|
|
||||||
# Join x86_64 and arm64 dynamic
|
# Join x86_64 and arm64 dynamic
|
||||||
lipo -create -output ../build/${{ env.RELEASE_NAME }}/lib/libraylib.${RAYLIB_VERSION}.dylib /tmp/libraylib_x86_64.${RAYLIB_VERSION}.dylib /tmp/libraylib_arm64.${RAYLIB_VERSION}.dylib
|
lipo -create -output ../build/${{ env.RELEASE_NAME }}/lib/libraylib.${RAYLIB_VERSION}.dylib /tmp/libraylib_x86_64.${RAYLIB_VERSION}.dylib /tmp/libraylib_arm64.${RAYLIB_VERSION}.dylib
|
||||||
ln -sv libraylib.${RAYLIB_VERSION}.dylib ../build/${{ env.RELEASE_NAME }}/lib/libraylib.dylib
|
ln -sv libraylib.${RAYLIB_VERSION}.dylib ../build/${{ env.RELEASE_NAME }}/lib/libraylib.dylib
|
||||||
ln -sv libraylib.${RAYLIB_VERSION}.dylib ../build/${{ env.RELEASE_NAME }}/lib/libraylib.${RAYLIB_API_VERSION}.dylib
|
ln -sv libraylib.${RAYLIB_VERSION}.dylib ../build/${{ env.RELEASE_NAME }}/lib/libraylib.${RAYLIB_API_VERSION}.dylib
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
- name: Generate Artifacts
|
- name: Generate Artifacts
|
||||||
run: |
|
run: |
|
||||||
cp -v ./src/raylib.h ./build/${{ env.RELEASE_NAME }}/include
|
cp -v ./src/raylib.h ./build/${{ env.RELEASE_NAME }}/include
|
||||||
|
|
@ -97,7 +97,7 @@ jobs:
|
||||||
cp -v ./LICENSE ./build/${{ env.RELEASE_NAME }}/LICENSE
|
cp -v ./LICENSE ./build/${{ env.RELEASE_NAME }}/LICENSE
|
||||||
cd build
|
cd build
|
||||||
tar -czvf ${{ env.RELEASE_NAME }}.tar.gz ${{ env.RELEASE_NAME }}
|
tar -czvf ${{ env.RELEASE_NAME }}.tar.gz ${{ env.RELEASE_NAME }}
|
||||||
|
|
||||||
- name: Upload Artifacts
|
- name: Upload Artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
|
|
@ -105,7 +105,7 @@ jobs:
|
||||||
path: |
|
path: |
|
||||||
./build/${{ env.RELEASE_NAME }}
|
./build/${{ env.RELEASE_NAME }}
|
||||||
!./build/${{ env.RELEASE_NAME }}.tar.gz
|
!./build/${{ env.RELEASE_NAME }}.tar.gz
|
||||||
|
|
||||||
- name: Upload Artifact to Release
|
- name: Upload Artifact to Release
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
4
.github/workflows/update_examples.yml
vendored
4
.github/workflows/update_examples.yml
vendored
|
|
@ -12,11 +12,11 @@ on:
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup emsdk
|
- name: Setup emsdk
|
||||||
uses: mymindstorm/setup-emsdk@v14
|
uses: mymindstorm/setup-emsdk@v14
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -118,6 +118,7 @@ GTAGS
|
||||||
# Zig programming language
|
# Zig programming language
|
||||||
.zig-cache/
|
.zig-cache/
|
||||||
zig-cache/
|
zig-cache/
|
||||||
|
zig-pkg/
|
||||||
zig-out/
|
zig-out/
|
||||||
build/
|
build/
|
||||||
build-*/
|
build-*/
|
||||||
|
|
|
||||||
54
CHANGELOG
54
CHANGELOG
|
|
@ -21,11 +21,17 @@ KEY CHANGES:
|
||||||
|
|
||||||
Detailed changes:
|
Detailed changes:
|
||||||
|
|
||||||
|
[rcore] ADDED: `FileRename()`, by @raysan5
|
||||||
|
[rcore] ADDED: `FileRemove()`, by @raysan5
|
||||||
|
[rcore] ADDED: `FileCopy()`, by @raysan5
|
||||||
|
[rcore] ADDED: `FileMove()`, by @raysan5
|
||||||
|
[rcore] ADDED: `FileTextReplace()`, by @raysan5
|
||||||
|
[rcore] ADDED: `FileTextFindIndex()`, by @raysan5
|
||||||
|
[rcore] ADDED: `ComputeSHA256()` (#5264) by @iamahuman1395
|
||||||
|
[rcore] ADDED: `GetKeyName()` (#4544) by @lecongsebastien
|
||||||
[rcore] ADDED: Logging and file-system functionality from `utils` (#4551) by @raysan5 -WARNING-
|
[rcore] ADDED: Logging and file-system functionality from `utils` (#4551) by @raysan5 -WARNING-
|
||||||
[rcore] ADDED: Flags set/clear macros: FLAG_SET, FLAG_CLEAR, FLAG_IS_SET (#5169) by @raysan5
|
[rcore] ADDED: Flags set/clear macros: FLAG_SET, FLAG_CLEAR, FLAG_IS_SET (#5169) by @raysan5
|
||||||
[rcore] ADDED: Warnings in case of no platform backend defined by @raysan5
|
[rcore] ADDED: Warnings in case of no platform backend defined by @raysan5
|
||||||
[rcore] ADDED: `ComputeSHA256()` (#5264) by @iamahuman1395
|
|
||||||
[rcore] ADDED: `GetKeyName()` (#4544) by @lecongsebastien
|
|
||||||
[rcore] REMOVED: GIF recording option, added example by @raysan5 -WARNING-
|
[rcore] REMOVED: GIF recording option, added example by @raysan5 -WARNING-
|
||||||
[rcore] REMOVED: `CORE.Window.fullscreen` variable, using available flag instead by @raysan5
|
[rcore] REMOVED: `CORE.Window.fullscreen` variable, using available flag instead by @raysan5
|
||||||
[rcore] REMOVED: `SetupFramebuffer()`, most platforms do not need it any more by @raysan5
|
[rcore] REMOVED: `SetupFramebuffer()`, most platforms do not need it any more by @raysan5
|
||||||
|
|
@ -111,7 +117,7 @@ Detailed changes:
|
||||||
[rcore][RGFW] ADDED: New backend option: `PLATFORM_WEB_RGFW` and update RGFW (#4480) by @colleagueRiley
|
[rcore][RGFW] ADDED: New backend option: `PLATFORM_WEB_RGFW` and update RGFW (#4480) by @colleagueRiley
|
||||||
[rcore][RGFW] REVIEWED: Added missing Right Control key by @M374LX
|
[rcore][RGFW] REVIEWED: Added missing Right Control key by @M374LX
|
||||||
[rcore][RGFW] REVIEWED: Changed `RGFW_window_eventWait` timeout to -1 by @doggymangc
|
[rcore][RGFW] REVIEWED: Changed `RGFW_window_eventWait` timeout to -1 by @doggymangc
|
||||||
[rcore][RGFW] REVIEWED: Duplicate entries reemoved from `keyMappingRGFW` (#5242) by @iamahuman1395
|
[rcore][RGFW] REVIEWED: Duplicate entries removed from `keyMappingRGFW` (#5242) by @iamahuman1395
|
||||||
[rcore][RGFW] REVIEWED: Fix Escape always closing the window by @M374LX
|
[rcore][RGFW] REVIEWED: Fix Escape always closing the window by @M374LX
|
||||||
[rcore][RGFW] REVIEWED: Forward declare the windows stuff, prevents failures in GCC (#5269) by @Jeffm2501
|
[rcore][RGFW] REVIEWED: Forward declare the windows stuff, prevents failures in GCC (#5269) by @Jeffm2501
|
||||||
[rcore][RGFW] REVIEWED: Requires RGBA8 images as window icons (#5431) by @crisserpl2
|
[rcore][RGFW] REVIEWED: Requires RGBA8 images as window icons (#5431) by @crisserpl2
|
||||||
|
|
@ -198,7 +204,7 @@ Detailed changes:
|
||||||
[rlgl] REVIEWED: `rlActiveDrawBuffers`, fix for OpenGL ES 3.0 (#4605) by @Bigfoot71
|
[rlgl] REVIEWED: `rlActiveDrawBuffers`, fix for OpenGL ES 3.0 (#4605) by @Bigfoot71
|
||||||
[rlgl] REVIEWED: `rlGetPixelDataSize()`, correct compressed data size calculation per blocks #5416 by @raysan5
|
[rlgl] REVIEWED: `rlGetPixelDataSize()`, correct compressed data size calculation per blocks #5416 by @raysan5
|
||||||
[rlgl] REVIEWED: `instranceTransform` shader location index #4538 (#4579) by @meadiode
|
[rlgl] REVIEWED: `instranceTransform` shader location index #4538 (#4579) by @meadiode
|
||||||
[rlgl] REVIEWED: `SetShaderValueTexture()`, updatee comments (#4703) by @pejorativefox
|
[rlgl] REVIEWED: `SetShaderValueTexture()`, update comments (#4703) by @pejorativefox
|
||||||
[rlgl] REDESIGNED: Avoid program crash if GPU data is tried to be loaded before `InitWindow()` #4751 by @raysan5 -WARNING-
|
[rlgl] REDESIGNED: Avoid program crash if GPU data is tried to be loaded before `InitWindow()` #4751 by @raysan5 -WARNING-
|
||||||
[rlgl] REDESIGNED: Shader loading API function names for more consistency #5631 by @raysan5 -WARNING-
|
[rlgl] REDESIGNED: Shader loading API function names for more consistency #5631 by @raysan5 -WARNING-
|
||||||
[rlsw] ADDED: `swGetColorBuffer()` for convenience by @raysan5
|
[rlsw] ADDED: `swGetColorBuffer()` for convenience by @raysan5
|
||||||
|
|
@ -239,6 +245,13 @@ Detailed changes:
|
||||||
[rtextures] REVIEWED: `ImageDrawLineEx(), to be able to draw even numbered thicknesses (#5042) by @Sir-Irk
|
[rtextures] REVIEWED: `ImageDrawLineEx(), to be able to draw even numbered thicknesses (#5042) by @Sir-Irk
|
||||||
[rtextures] REVIEWED: `ImageBlurGaussian()`, fix integer overflow in cast (#5037) by @garrisonhh
|
[rtextures] REVIEWED: `ImageBlurGaussian()`, fix integer overflow in cast (#5037) by @garrisonhh
|
||||||
[rtext] ADDED: `LoadTextLines()`/`UnloadTextLines()` by @raysan5
|
[rtext] ADDED: `LoadTextLines()`/`UnloadTextLines()` by @raysan5
|
||||||
|
[rtext] ADDED: `TextInsertAlloc()`, returns memory allocated string by @raysan5
|
||||||
|
[rtext] ADDED: `TextReplace()`, using static buffer by @raysan5
|
||||||
|
[rtext] ADDED: `TextReplaceAlloc()`, returns memory allocated string by @raysan5
|
||||||
|
[rtext] ADDED: `TextReplaceBetween()`, using static buffer by @raysan5
|
||||||
|
[rtext] ADDED: `TextReplaceBetweenAlloc()`, returns memory allocated string by @raysan5
|
||||||
|
[rtext] ADDED: `GetTextBetween()`, using static buffer by @raysan5
|
||||||
|
[rtext] ADDED: `TextRemoveSpaces()`, using static buffer by @raysan5
|
||||||
[rtext] ADDED: `MeasureTextCodepoints()` for direct measurement of codepoints (#5623) by @creeperblin
|
[rtext] ADDED: `MeasureTextCodepoints()` for direct measurement of codepoints (#5623) by @creeperblin
|
||||||
[rtext] RENAMED: Variable names for consistency, `textLength` (length in bytes) vs `textSize` (measure in pixels) by @raysan5
|
[rtext] RENAMED: Variable names for consistency, `textLength` (length in bytes) vs `textSize` (measure in pixels) by @raysan5
|
||||||
[rtext] REVIEWED: Support default font loading with no GPU enabled, to be used with Image API
|
[rtext] REVIEWED: Support default font loading with no GPU enabled, to be used with Image API
|
||||||
|
|
@ -263,11 +276,10 @@ Detailed changes:
|
||||||
[rtext] REVIEWED: `GetCodepointCount()`, misuse of cast (#4741) by @sleeptightAnsiC
|
[rtext] REVIEWED: `GetCodepointCount()`, misuse of cast (#4741) by @sleeptightAnsiC
|
||||||
[rtext] REVIEWED: `GenImageFontAtlas()`, memory corruption and invalid size calculation (#5602) by @konakona418
|
[rtext] REVIEWED: `GenImageFontAtlas()`, memory corruption and invalid size calculation (#5602) by @konakona418
|
||||||
[rtext] REVIEWED: `TextInsert()`, fix bug on insertion (#5644) by @CrackedPixel
|
[rtext] REVIEWED: `TextInsert()`, fix bug on insertion (#5644) by @CrackedPixel
|
||||||
|
[rtext] REVIEWED: `TextInsert()`, use static buffer, easier to use by @raysan5 -WARNING-
|
||||||
[rtext] REVIEWED: `TextJoin()`, convert `const char **` to `char**` by @raysan5
|
[rtext] REVIEWED: `TextJoin()`, convert `const char **` to `char**` by @raysan5
|
||||||
[rtext] REVIEWED: `TextReplace()` and `TextLength()`, avoid using `strcpy()` by @raysan5
|
|
||||||
[rtext] REVIEWED: `TextReplace()` by @raysan5
|
|
||||||
[rtext] REVIEWED: `TextReplace()`, improvements (#5511) by @belan2470
|
[rtext] REVIEWED: `TextReplace()`, improvements (#5511) by @belan2470
|
||||||
[rtext] REVIEWED: `TextReplaceBetween()` by @raysan5
|
[rtext] REVIEWED: `TextReplace()` and `TextLength()`, avoid using `strcpy()` by @raysan5
|
||||||
[rtext] REVIEWED: `TextSubtext(), fixes (#4759) by @veins1
|
[rtext] REVIEWED: `TextSubtext(), fixes (#4759) by @veins1
|
||||||
[rtext] REVIEWED: `TextToPascal()`, fix issue by @raysan5
|
[rtext] REVIEWED: `TextToPascal()`, fix issue by @raysan5
|
||||||
[rtext] REVIEWED: `TextToFloat()`, remove removed inaccurate comment (#4596) by @hexmaster111
|
[rtext] REVIEWED: `TextToFloat()`, remove removed inaccurate comment (#4596) by @hexmaster111
|
||||||
|
|
@ -735,7 +747,7 @@ Detailed changes:
|
||||||
[rexm] REVIEWED: `ScanExampleResources()` avoid resources to be saved by the program by @raysan5
|
[rexm] REVIEWED: `ScanExampleResources()` avoid resources to be saved by the program by @raysan5
|
||||||
[rexm] REVIEWED: `UpdateSourceMetadata()` and `TextReplaceBetween()` by @raysan5
|
[rexm] REVIEWED: `UpdateSourceMetadata()` and `TextReplaceBetween()` by @raysan5
|
||||||
[rexm] REVIEWED: `examples.js` example addition working by @raysan5
|
[rexm] REVIEWED: `examples.js` example addition working by @raysan5
|
||||||
[rexm] REVIEWED: `add` command logic for existing examplee addition by @raysan5
|
[rexm] REVIEWED: `add` command logic for existing example addition by @raysan5
|
||||||
[rexm] REVIEWED: Replace example name on project file by @raysan5
|
[rexm] REVIEWED: Replace example name on project file by @raysan5
|
||||||
[rexm] REVIEWED: Report issues if logs can not be loaded by @raysan5
|
[rexm] REVIEWED: Report issues if logs can not be loaded by @raysan5
|
||||||
[rexm] REVIEWED: VS project adding to solution by @raysan5
|
[rexm] REVIEWED: VS project adding to solution by @raysan5
|
||||||
|
|
@ -747,6 +759,7 @@ Detailed changes:
|
||||||
[rexm] REVIEWED: `Makefile.Web` before trying to rebuild new example for web by @raysan5
|
[rexm] REVIEWED: `Makefile.Web` before trying to rebuild new example for web by @raysan5
|
||||||
[rexm] REVIEWED: Using `Makefile.Web` for specific web versions generation by @raysan5
|
[rexm] REVIEWED: Using `Makefile.Web` for specific web versions generation by @raysan5
|
||||||
|
|
||||||
|
[external] ADDED: `cgltf_write` 1.15, to support glTF models export in the future, by @raysan5
|
||||||
[external] RENAMED: `rl_gputex.h` to `rltexgpu.h`, compressed textures loading
|
[external] RENAMED: `rl_gputex.h` to `rltexgpu.h`, compressed textures loading
|
||||||
[external] REVIEWED: `rltexgpu.h`, make it usable standalone by @raysan5
|
[external] REVIEWED: `rltexgpu.h`, make it usable standalone by @raysan5
|
||||||
[external] REVIEWED: `rltexgpu.h, fix the swizzling in `rl_load_dds_from_memory()` (#5422) by @msmith-codes
|
[external] REVIEWED: `rltexgpu.h, fix the swizzling in `rl_load_dds_from_memory()` (#5422) by @msmith-codes
|
||||||
|
|
@ -755,16 +768,23 @@ Detailed changes:
|
||||||
[external] REVIEWED: `sdefl` and `sinfl` issues (#5367) by @raysan5
|
[external] REVIEWED: `sdefl` and `sinfl` issues (#5367) by @raysan5
|
||||||
[external] REVIEWED: `sinfl_bsr()`, improvements by @RicoP
|
[external] REVIEWED: `sinfl_bsr()`, improvements by @RicoP
|
||||||
[external] REVIEWED: `stb_truetype`, fix composite glyph scaling logic (#4811) by @ashishbhattarai
|
[external] REVIEWED: `stb_truetype`, fix composite glyph scaling logic (#4811) by @ashishbhattarai
|
||||||
|
[external] UPDATED: `raygui` to 5.0-dev for examples by @raysan5
|
||||||
[external] UPDATED: dr_libs (#5020) by @Emil2010
|
[external] UPDATED: dr_libs (#5020) by @Emil2010
|
||||||
[external] UPDATED: miniaudio to v0.11.22 (#4983) by @M374LX
|
[external] UPDATED: `miniaudio` to v0.11.22 (#4983) by @M374LX
|
||||||
[external] UPDATED: miniaudio to v0.11.23 (#5234) by @pyrokn8
|
[external] UPDATED: `miniaudio` to v0.11.23 (#5234) by @pyrokn8
|
||||||
[external] UPDATED: miniaudio to v0.11.24 (#5506) by @vdemcak
|
[external] UPDATED: `miniaudio` to v0.11.24 (#5506) by @vdemcak
|
||||||
[external] UPDATED: raygui to 5.0-dev for examples by @raysan5
|
[external] UPDATED: `RGFW` to 1.5 (#4688) by @ColleagueRiley
|
||||||
[external] UPDATED: RGFW to 1.5 (#4688) by @ColleagueRiley
|
[external] UPDATED: `RGFW` to 1.6 (#4795) by @colleagueRiley
|
||||||
[external] UPDATED: RGFW to 1.6 (#4795) by @colleagueRiley
|
[external] UPDATED: `RGFW` to 1.7 (#4965) by @M374LX
|
||||||
[external] UPDATED: RGFW to 1.7 (#4965) by @M374LX
|
[external] UPDATED: `RGFW` to 1.7.5-dev (#4976) by @M374LX
|
||||||
[external] UPDATED: RGFW to 1.7.5-dev (#4976) by @M374LX
|
[external] UPDATED: `RGFW` to 2.0.0 (#5582) by @CrackedPixel
|
||||||
[external] UPDATED: RGFW to 2.0.0 (#5582) by @CrackedPixel
|
[external] UPDATED: `cgltf` 1.14 to 1.15 by @raysan5
|
||||||
|
[external] UPDATED: `dr_flac` v0.13.0 to v0.13.3 by @raysan5
|
||||||
|
[external] UPDATED: `dr_mp3` v0.7.0 to v0.7.4 by @raysan5
|
||||||
|
[external] UPDATED: `m3d` to latest master by @raysan5
|
||||||
|
[external] UPDATED: `qoi` to latest master by @raysan5
|
||||||
|
[external] UPDATED: `qoa` to latest master by @raysan5
|
||||||
|
[external] UPDATED: `stb_image_resize2` v2.12 to v2.18 by @raysan5
|
||||||
|
|
||||||
[misc] ADDED: SECURITY.md for security reporting policies by @raysan5
|
[misc] ADDED: SECURITY.md for security reporting policies by @raysan5
|
||||||
[misc] ADDED: `examples/examples_list`, to be used by `rexm` or other tools by @raysan5
|
[misc] ADDED: `examples/examples_list`, to be used by `rexm` or other tools by @raysan5
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ features
|
||||||
- Written in plain C code (C99) using PascalCase/camelCase notation
|
- Written in plain C code (C99) using PascalCase/camelCase notation
|
||||||
- Hardware accelerated with OpenGL: **1.1, 2.1, 3.3, 4.3, ES 2.0, ES 3.0**
|
- Hardware accelerated with OpenGL: **1.1, 2.1, 3.3, 4.3, ES 2.0, ES 3.0**
|
||||||
- **Unique OpenGL abstraction layer** (usable as standalone module): [rlgl](https://github.com/raysan5/raylib/blob/master/src/rlgl.h)
|
- **Unique OpenGL abstraction layer** (usable as standalone module): [rlgl](https://github.com/raysan5/raylib/blob/master/src/rlgl.h)
|
||||||
|
- **Software Renderer** backend (no OpenGL required!): [rlsw](https://github.com/raysan5/raylib/blob/master/src/external/rlsw.h)
|
||||||
- Multiple **Fonts** formats supported (TTF, OTF, FNT, BDF, sprite fonts)
|
- Multiple **Fonts** formats supported (TTF, OTF, FNT, BDF, sprite fonts)
|
||||||
- Multiple texture formats supported, including **compressed formats** (DXT, ETC, ASTC)
|
- Multiple texture formats supported, including **compressed formats** (DXT, ETC, ASTC)
|
||||||
- **Full 3D support**, including 3D Shapes, Models, Billboards, Heightmaps and more!
|
- **Full 3D support**, including 3D Shapes, Models, Billboards, Heightmaps and more!
|
||||||
|
|
@ -61,7 +62,7 @@ This is a basic raylib example, it creates a window and draws the text `"Congrat
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
InitWindow(800, 450, "raylib [core] example - basic window");
|
InitWindow(800, 450, "raylib example - basic window");
|
||||||
|
|
||||||
while (!WindowShouldClose())
|
while (!WindowShouldClose())
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ Here is a wishlist with features and ideas to improve the library. Note that fea
|
||||||
- [GitHub PRs](https://github.com/raysan5/raylib/pulls) open with improvements to be reviewed.
|
- [GitHub PRs](https://github.com/raysan5/raylib/pulls) open with improvements to be reviewed.
|
||||||
- [raylib source code](https://github.com/raysan5/raylib/tree/master/src) has multiple *TODO* comments around code with pending things to review or improve.
|
- [raylib source code](https://github.com/raysan5/raylib/tree/master/src) has multiple *TODO* comments around code with pending things to review or improve.
|
||||||
- raylib wishlists discussions are open to everyone to ask for improvements, feel free to check and comment:
|
- raylib wishlists discussions are open to everyone to ask for improvements, feel free to check and comment:
|
||||||
|
- [raylib 7.0 wishlist](https://github.com/raysan5/raylib/discussions/5710)
|
||||||
- [raylib 6.0 wishlist](https://github.com/raysan5/raylib/discussions/4660)
|
- [raylib 6.0 wishlist](https://github.com/raysan5/raylib/discussions/4660)
|
||||||
- [raylib 5.0 wishlist](https://github.com/raysan5/raylib/discussions/2952)
|
- [raylib 5.0 wishlist](https://github.com/raysan5/raylib/discussions/2952)
|
||||||
- [raylib wishlist 2022](https://github.com/raysan5/raylib/discussions/2272)
|
- [raylib wishlist 2022](https://github.com/raysan5/raylib/discussions/2272)
|
||||||
|
|
@ -21,7 +22,7 @@ _Current version of raylib is complete and functional but there is always room f
|
||||||
- [ ] `rcore_desktop_wayland`: Create additional platform backend: Linux/Wayland
|
- [ ] `rcore_desktop_wayland`: Create additional platform backend: Linux/Wayland
|
||||||
- [ ] `rcore`: Investigate alternative embedded platforms and realtime OSs
|
- [ ] `rcore`: Investigate alternative embedded platforms and realtime OSs
|
||||||
- [ ] `rlsw`: Software renderer optimizations: mipmaps, platform-specific SIMD
|
- [ ] `rlsw`: Software renderer optimizations: mipmaps, platform-specific SIMD
|
||||||
- [ ] `rtextures`: Consider moving N-patch system to separate example
|
- [ ] `rtextures`: Consider removing N-patch system, provide as separate example
|
||||||
- [ ] `rtextures`: Review blending modes system, provide more options or better samples
|
- [ ] `rtextures`: Review blending modes system, provide more options or better samples
|
||||||
- [ ] `rtext`: Investigate the recently opened [`Slug`](https://sluglibrary.com/) font rendering algorithm
|
- [ ] `rtext`: Investigate the recently opened [`Slug`](https://sluglibrary.com/) font rendering algorithm
|
||||||
- [ ] `raudio`: Support microphone input, basic API to read microphone
|
- [ ] `raudio`: Support microphone input, basic API to read microphone
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
/// Minimum supported version of Zig
|
/// Minimum supported version of Zig
|
||||||
const min_ver = "0.16.0-dev.2349+204fa8959";
|
const min_ver = "0.16.0-dev.3013+abd131e33";
|
||||||
|
|
||||||
const emccOutputDir = "zig-out" ++ std.fs.path.sep_str ++ "htmlout" ++ std.fs.path.sep_str;
|
const emccOutputDir = "zig-out" ++ std.fs.path.sep_str ++ "htmlout" ++ std.fs.path.sep_str;
|
||||||
const emccOutputFile = "index.html";
|
const emccOutputFile = "index.html";
|
||||||
|
|
@ -264,7 +264,10 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
|
||||||
|
|
||||||
setDesktopPlatform(raylib, .android);
|
setDesktopPlatform(raylib, .android);
|
||||||
} else {
|
} else {
|
||||||
try c_source_files.append(b.allocator, "src/rglfw.c");
|
switch (options.platform) {
|
||||||
|
.glfw => try c_source_files.append(b.allocator, "src/rglfw.c"),
|
||||||
|
.rgfw, .sdl, .drm, .android => {},
|
||||||
|
}
|
||||||
|
|
||||||
if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) {
|
if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) {
|
||||||
raylib.root_module.addCMacro("_GLFW_X11", "");
|
raylib.root_module.addCMacro("_GLFW_X11", "");
|
||||||
|
|
@ -434,6 +437,7 @@ pub const OpenglVersion = enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const LinuxDisplayBackend = enum {
|
pub const LinuxDisplayBackend = enum {
|
||||||
|
None,
|
||||||
X11,
|
X11,
|
||||||
Wayland,
|
Wayland,
|
||||||
Both,
|
Both,
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@
|
||||||
|
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
.xcode_frameworks = .{
|
.xcode_frameworks = .{
|
||||||
.url = "https://pkg.machengine.org/xcode-frameworks/9a45f3ac977fd25dff77e58c6de1870b6808c4a7.tar.gz",
|
.url = "https://pkg.machengine.org/xcode-frameworks/8a1cfb373587ea4c9bb1468b7c986462d8d4e10e.tar.gz",
|
||||||
.hash = "122098b9174895f9708bc824b0f9e550c401892c40a900006459acf2cbf78acd99bb",
|
.hash = "N-V-__8AALShqgXkvqYU6f__FrA22SMWmi2TXCJjNTO1m8XJ",
|
||||||
.lazy = true,
|
.lazy = true,
|
||||||
},
|
},
|
||||||
.emsdk = .{
|
.emsdk = .{
|
||||||
|
|
|
||||||
|
|
@ -1153,7 +1153,10 @@ text/text_font_filters: text/text_font_filters.c
|
||||||
--preload-file text/resources/KAISG.ttf@resources/KAISG.ttf
|
--preload-file text/resources/KAISG.ttf@resources/KAISG.ttf
|
||||||
|
|
||||||
text/text_font_loading: text/text_font_loading.c
|
text/text_font_loading: text/text_font_loading.c
|
||||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
|
||||||
|
--preload-file text/resources/pixantiqua.fnt@resources/pixantiqua.fnt \
|
||||||
|
--preload-file text/resources/pixantiqua.png@resources/pixantiqua.png \
|
||||||
|
--preload-file text/resources/pixantiqua.ttf@resources/pixantiqua.ttf
|
||||||
|
|
||||||
text/text_font_sdf: text/text_font_sdf.c
|
text/text_font_sdf: text/text_font_sdf.c
|
||||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
|
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
|
||||||
|
|
|
||||||
238
examples/audio/audio_amp_envelope.c
Normal file
238
examples/audio/audio_amp_envelope.c
Normal file
|
|
@ -0,0 +1,238 @@
|
||||||
|
/*******************************************************************************************
|
||||||
|
*
|
||||||
|
* raylib [audio] example - amp envelope
|
||||||
|
*
|
||||||
|
* Example complexity rating: [★☆☆☆] 1/4
|
||||||
|
*
|
||||||
|
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||||
|
*
|
||||||
|
* Example contributed by Arbinda Rizki Muhammad (@arbipink) and reviewed by Ramon Santamaria (@raysan5)
|
||||||
|
*
|
||||||
|
* 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 Arbinda Rizki Muhammad (@arbipink)
|
||||||
|
*
|
||||||
|
********************************************************************************************/
|
||||||
|
|
||||||
|
#include "raylib.h"
|
||||||
|
|
||||||
|
#define RAYGUI_IMPLEMENTATION
|
||||||
|
#include "raygui.h"
|
||||||
|
|
||||||
|
#include <math.h> // Required for: sinf()
|
||||||
|
|
||||||
|
#define BUFFER_SIZE 4096
|
||||||
|
#define SAMPLE_RATE 44100
|
||||||
|
|
||||||
|
// Wave state
|
||||||
|
typedef enum {
|
||||||
|
IDLE,
|
||||||
|
ATTACK,
|
||||||
|
DECAY,
|
||||||
|
SUSTAIN,
|
||||||
|
RELEASE
|
||||||
|
} ADSRState;
|
||||||
|
|
||||||
|
// Grouping all ADSR parameters and state into a struct
|
||||||
|
typedef struct {
|
||||||
|
float attackTime;
|
||||||
|
float decayTime;
|
||||||
|
float sustainLevel;
|
||||||
|
float releaseTime;
|
||||||
|
float currentValue;
|
||||||
|
ADSRState state;
|
||||||
|
} Envelope;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Module Functions Declaration
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
static void FillAudioBuffer(int i, float *buffer, float envelopeValue, float *audioTime);
|
||||||
|
static void UpdateEnvelope(Envelope *env);
|
||||||
|
static void DrawADSRGraph(Envelope *env, Rectangle bounds);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Program main entry point
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
// Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
const int screenWidth = 800;
|
||||||
|
const int screenHeight = 450;
|
||||||
|
|
||||||
|
InitWindow(screenWidth, screenHeight, "raylib [audio] example - amp envelope");
|
||||||
|
|
||||||
|
InitAudioDevice();
|
||||||
|
|
||||||
|
// Set the number of samples the stream will keep in memory at a time to BUFFER_SIZE
|
||||||
|
SetAudioStreamBufferSizeDefault(BUFFER_SIZE);
|
||||||
|
float buffer[BUFFER_SIZE] = { 0 };
|
||||||
|
|
||||||
|
// Init raw audio stream (sample rate: 44100, sample size: 32bit-float, channels: 1-mono)
|
||||||
|
AudioStream stream = LoadAudioStream(SAMPLE_RATE, 32, 1);
|
||||||
|
|
||||||
|
// Init Phase
|
||||||
|
float audioTime = 0.0f;
|
||||||
|
|
||||||
|
// Initialize the struct
|
||||||
|
Envelope env = {
|
||||||
|
.attackTime = 1.0f,
|
||||||
|
.decayTime = 1.0f,
|
||||||
|
.sustainLevel = 0.5f,
|
||||||
|
.releaseTime = 1.0f,
|
||||||
|
.currentValue = 0.0f,
|
||||||
|
.state = IDLE
|
||||||
|
};
|
||||||
|
|
||||||
|
SetTargetFPS(60);
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Main game loop
|
||||||
|
while (!WindowShouldClose())
|
||||||
|
{
|
||||||
|
// Update
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
if (IsKeyPressed(KEY_SPACE)) env.state = ATTACK;
|
||||||
|
|
||||||
|
if (IsKeyReleased(KEY_SPACE) && (env.state != IDLE)) env.state = RELEASE;
|
||||||
|
|
||||||
|
if (IsAudioStreamProcessed(stream))
|
||||||
|
{
|
||||||
|
if ((env.state != IDLE) || (env.currentValue > 0.0f))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < BUFFER_SIZE; i++)
|
||||||
|
{
|
||||||
|
UpdateEnvelope(&env);
|
||||||
|
FillAudioBuffer(i, buffer, env.currentValue, &audioTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Clear buffer if silent to avoid looping noise
|
||||||
|
for (int i = 0; i < BUFFER_SIZE; i++) buffer[i] = 0;
|
||||||
|
audioTime = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateAudioStream(stream, buffer, BUFFER_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsAudioStreamPlaying(stream)) PlayAudioStream(stream);
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Draw
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
BeginDrawing();
|
||||||
|
|
||||||
|
ClearBackground(RAYWHITE);
|
||||||
|
|
||||||
|
GuiSliderBar((Rectangle){ 100, 60, 400, 30 }, "Attack (s)", TextFormat("%2.2fs", env.attackTime), &env.attackTime, 0.1f, 3.0f);
|
||||||
|
GuiSliderBar((Rectangle){ 100, 100, 400, 30 }, "Decay (s)", TextFormat("%2.2fs", env.decayTime), &env.decayTime, 0.1f, 3.0f);
|
||||||
|
GuiSliderBar((Rectangle){ 100, 140, 400, 30 }, "Sustain", TextFormat("%2.2f", env.sustainLevel), &env.sustainLevel, 0.0f, 1.0f);
|
||||||
|
GuiSliderBar((Rectangle){ 100, 180, 400, 30 }, "Release (s)", TextFormat("%2.2fs", env.releaseTime), &env.releaseTime, 0.1f, 3.0f);
|
||||||
|
|
||||||
|
DrawADSRGraph(&env, (Rectangle){ 100, 250, 400, 100 });
|
||||||
|
|
||||||
|
DrawCircleV((Vector2){ 520, 350 - (env.currentValue * 100) }, 5, MAROON);
|
||||||
|
DrawText(TextFormat("Current Gain: %2.2f", env.currentValue), 535, 345 - (env.currentValue * 100), 10, MAROON);
|
||||||
|
|
||||||
|
DrawText("Press SPACE to PLAY the sound!", 200, 400, 20, LIGHTGRAY);
|
||||||
|
|
||||||
|
EndDrawing();
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
}
|
||||||
|
|
||||||
|
// De-Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
UnloadAudioStream(stream);
|
||||||
|
CloseAudioDevice();
|
||||||
|
|
||||||
|
CloseWindow();
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Module Functions Definition
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
static void FillAudioBuffer(int i, float *buffer, float envelopeValue, float *audioTime)
|
||||||
|
{
|
||||||
|
int frequency = 440;
|
||||||
|
buffer[i] = envelopeValue*sinf(2.0f*PI*frequency*(*audioTime));
|
||||||
|
*audioTime += (1.0f/SAMPLE_RATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void UpdateEnvelope(Envelope *env)
|
||||||
|
{
|
||||||
|
// Calculate the time delta for ONE sample (1/44100)
|
||||||
|
float sampleTime = 1.0f/SAMPLE_RATE;
|
||||||
|
|
||||||
|
switch(env->state)
|
||||||
|
{
|
||||||
|
case ATTACK:
|
||||||
|
{
|
||||||
|
env->currentValue += (1.0f/env->attackTime)*sampleTime;
|
||||||
|
if (env->currentValue >= 1.0f)
|
||||||
|
{
|
||||||
|
env->currentValue = 1.0f;
|
||||||
|
env->state = DECAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case DECAY:
|
||||||
|
{
|
||||||
|
env->currentValue -= ((1.0f - env->sustainLevel)/env->decayTime)*sampleTime;
|
||||||
|
if (env->currentValue <= env->sustainLevel)
|
||||||
|
{
|
||||||
|
env->currentValue = env->sustainLevel;
|
||||||
|
env->state = SUSTAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case SUSTAIN:
|
||||||
|
{
|
||||||
|
env->currentValue = env->sustainLevel;
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case RELEASE:
|
||||||
|
{
|
||||||
|
env->currentValue -= (env->sustainLevel/env->releaseTime)*sampleTime;
|
||||||
|
if (env->currentValue <= 0.001f) // Use a small threshold to avoid infinite tail
|
||||||
|
{
|
||||||
|
env->currentValue = 0.0f;
|
||||||
|
env->state = IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
} break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DrawADSRGraph(Envelope *env, Rectangle bounds)
|
||||||
|
{
|
||||||
|
DrawRectangleRec(bounds, Fade(LIGHTGRAY, 0.3f));
|
||||||
|
DrawRectangleLinesEx(bounds, 1, GRAY);
|
||||||
|
|
||||||
|
// Fixed visual width for sustain stage since it's an amplitude not a time value
|
||||||
|
float sustainWidth = 1.0f;
|
||||||
|
|
||||||
|
// Total time to visualize (sum of A, D, R + a padding for Sustain)
|
||||||
|
float totalTime = env->attackTime + env->decayTime + sustainWidth + env->releaseTime;
|
||||||
|
|
||||||
|
float scaleX = bounds.width/totalTime;
|
||||||
|
float scaleY = bounds.height;
|
||||||
|
|
||||||
|
Vector2 start = { bounds.x, bounds.y + bounds.height };
|
||||||
|
Vector2 peak = { start.x + (env->attackTime*scaleX), bounds.y };
|
||||||
|
Vector2 sustain = { peak.x + (env->decayTime*scaleX), bounds.y + (1.0f - env->sustainLevel)*scaleY };
|
||||||
|
Vector2 rel = { sustain.x + (sustainWidth*scaleX), sustain.y };
|
||||||
|
Vector2 end = { rel.x + (env->releaseTime*scaleX), bounds.y + bounds.height };
|
||||||
|
|
||||||
|
DrawLineV(start, peak, SKYBLUE);
|
||||||
|
DrawLineV(peak, sustain, BLUE);
|
||||||
|
DrawLineV(sustain, rel, DARKBLUE);
|
||||||
|
DrawLineV(rel, end, ORANGE);
|
||||||
|
|
||||||
|
DrawText("ADSR Visualizer", bounds.x, bounds.y - 20, 10, DARKGRAY);
|
||||||
|
}
|
||||||
BIN
examples/audio/audio_amp_envelope.png
Normal file
BIN
examples/audio/audio_amp_envelope.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
6051
examples/audio/raygui.h
Normal file
6051
examples/audio/raygui.h
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -23,15 +23,15 @@ void main()
|
||||||
float localX = mod(fragCoord.x, cellWidth);
|
float localX = mod(fragCoord.x, cellWidth);
|
||||||
float barWidth = cellWidth - 1.0;
|
float barWidth = cellWidth - 1.0;
|
||||||
vec4 color = WHITE;
|
vec4 color = WHITE;
|
||||||
|
|
||||||
if (localX <= barWidth)
|
if (localX <= barWidth)
|
||||||
{
|
{
|
||||||
float sampleX = (binIndex + 0.5)/NUM_OF_BINS;
|
float sampleX = (binIndex + 0.5)/NUM_OF_BINS;
|
||||||
vec2 sampleCoord = vec2(sampleX, FFT_ROW);
|
vec2 sampleCoord = vec2(sampleX, FFT_ROW);
|
||||||
float amplitude = texture2D(iChannel0, sampleCoord).r; // Only filled the red channel, all channels left open for alternative use
|
float amplitude = texture2D(iChannel0, sampleCoord).r; // Only filled the red channel, all channels left open for alternative use
|
||||||
|
|
||||||
if (fragTexCoord.y < amplitude) color = BLACK;
|
if (fragTexCoord.y < amplitude) color = BLACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
gl_FragColor = color;
|
gl_FragColor = color;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,15 +21,15 @@ void main()
|
||||||
float localX = mod(fragCoord.x, cellWidth);
|
float localX = mod(fragCoord.x, cellWidth);
|
||||||
float barWidth = cellWidth - 1.0;
|
float barWidth = cellWidth - 1.0;
|
||||||
vec4 color = WHITE;
|
vec4 color = WHITE;
|
||||||
|
|
||||||
if (localX <= barWidth)
|
if (localX <= barWidth)
|
||||||
{
|
{
|
||||||
float sampleX = (binIndex + 0.5)/NUM_OF_BINS;
|
float sampleX = (binIndex + 0.5)/NUM_OF_BINS;
|
||||||
vec2 sampleCoord = vec2(sampleX, FFT_ROW);
|
vec2 sampleCoord = vec2(sampleX, FFT_ROW);
|
||||||
float amplitude = texture2D(iChannel0, sampleCoord).r; // Only filled the red channel, all channels left open for alternative use
|
float amplitude = texture2D(iChannel0, sampleCoord).r; // Only filled the red channel, all channels left open for alternative use
|
||||||
|
|
||||||
if (fragTexCoord.y < amplitude) color = BLACK;
|
if (fragTexCoord.y < amplitude) color = BLACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
gl_FragColor = color;
|
gl_FragColor = color;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,15 +21,15 @@ void main()
|
||||||
float localX = mod(fragCoord.x, cellWidth);
|
float localX = mod(fragCoord.x, cellWidth);
|
||||||
float barWidth = cellWidth - 1.0;
|
float barWidth = cellWidth - 1.0;
|
||||||
vec4 color = WHITE;
|
vec4 color = WHITE;
|
||||||
|
|
||||||
if (localX <= barWidth)
|
if (localX <= barWidth)
|
||||||
{
|
{
|
||||||
float sampleX = (binIndex + 0.5)/NUM_OF_BINS;
|
float sampleX = (binIndex + 0.5)/NUM_OF_BINS;
|
||||||
vec2 sampleCoord = vec2(sampleX, FFT_ROW);
|
vec2 sampleCoord = vec2(sampleX, FFT_ROW);
|
||||||
float amplitude = texture(iChannel0, sampleCoord).r; // Only filled the red channel, all channels left open for alternative use
|
float amplitude = texture(iChannel0, sampleCoord).r; // Only filled the red channel, all channels left open for alternative use
|
||||||
|
|
||||||
if (fragTexCoord.y < amplitude) color = BLACK;
|
if (fragTexCoord.y < amplitude) color = BLACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
finalColor = color;
|
finalColor = color;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ int main(void)
|
||||||
decalMaterial.maps[MATERIAL_MAP_DIFFUSE].color = RAYWHITE;
|
decalMaterial.maps[MATERIAL_MAP_DIFFUSE].color = RAYWHITE;
|
||||||
|
|
||||||
bool showModel = true;
|
bool showModel = true;
|
||||||
Model decalModels[MAX_DECALS] = { 0 };
|
static Model decalModels[MAX_DECALS] = { 0 };
|
||||||
int decalCount = 0;
|
int decalCount = 0;
|
||||||
|
|
||||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
********************************************************************************************/
|
********************************************************************************************/
|
||||||
|
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
|
#include "rlgl.h"
|
||||||
|
|
||||||
#include <stdlib.h> // Required for: rand()
|
#include <stdlib.h> // Required for: rand()
|
||||||
#include <math.h> // Required for: cosf(), sinf()
|
#include <math.h> // Required for: cosf(), sinf()
|
||||||
|
|
@ -26,8 +27,9 @@
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Module Functions Declaration
|
// Module Functions Declaration
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Generate mesh using points
|
static Mesh GenMeshPoints(int numPoints); // Generate mesh using points
|
||||||
static Mesh GenMeshPoints(int numPoints);
|
void DrawModelPoints(Model model, Vector3 position, float scale, Color tint); // Draw a model as points
|
||||||
|
void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model as points with extended parameters
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Program main entry point
|
// Program main entry point
|
||||||
|
|
@ -184,3 +186,30 @@ static Mesh GenMeshPoints(int numPoints)
|
||||||
|
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Draw a model points
|
||||||
|
// WARNING: OpenGL ES 2.0 does not support point mode drawing
|
||||||
|
void DrawModelPoints(Model model, Vector3 position, float scale, Color tint)
|
||||||
|
{
|
||||||
|
rlEnablePointMode();
|
||||||
|
rlDisableBackfaceCulling();
|
||||||
|
|
||||||
|
DrawModel(model, position, scale, tint);
|
||||||
|
|
||||||
|
rlEnableBackfaceCulling();
|
||||||
|
rlDisablePointMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a model points
|
||||||
|
// WARNING: OpenGL ES 2.0 does not support point mode drawing
|
||||||
|
void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint)
|
||||||
|
{
|
||||||
|
rlEnablePointMode();
|
||||||
|
rlDisableBackfaceCulling();
|
||||||
|
|
||||||
|
DrawModelEx(model, position, rotationAxis, rotationAngle, scale, tint);
|
||||||
|
|
||||||
|
rlEnableBackfaceCulling();
|
||||||
|
rlDisablePointMode();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,9 @@
|
||||||
| models/vox/chr_knight.vox | ❔ | ❔ | - |
|
| models/vox/chr_knight.vox | ❔ | ❔ | - |
|
||||||
| models/vox/chr_sword.vox | ❔ | ❔ | - |
|
| models/vox/chr_sword.vox | ❔ | ❔ | - |
|
||||||
| models/vox/monu9.vox | ❔ | ❔ | - |
|
| models/vox/monu9.vox | ❔ | ❔ | - |
|
||||||
| billboard.png | [@emegeme](https://github.com/emegeme) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
|
| billboard.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
|
||||||
| cubicmap.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
|
| cubicmap.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
|
||||||
| cubicmap_atlas.png | [@emegeme](https://github.com/emegeme) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
|
| cubicmap_atlas.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
|
||||||
| heightmap.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
|
| heightmap.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
|
||||||
| dresden_square_1k.hdr | [HDRIHaven](https://hdrihaven.com/hdri/?h=dresden_square) | [CC0](https://hdrihaven.com/p/license.php) | - |
|
| dresden_square_1k.hdr | [HDRIHaven](https://hdrihaven.com/hdri/?h=dresden_square) | [CC0](https://hdrihaven.com/p/license.php) | - |
|
||||||
| dresden_square_2k.hdr | [HDRIHaven](https://hdrihaven.com/hdri/?h=dresden_square) | [CC0](https://hdrihaven.com/p/license.php) | - |
|
| dresden_square_2k.hdr | [HDRIHaven](https://hdrihaven.com/hdri/?h=dresden_square) | [CC0](https://hdrihaven.com/p/license.php) | - |
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ void main()
|
||||||
{
|
{
|
||||||
// Fetch color from texture sampler
|
// Fetch color from texture sampler
|
||||||
vec4 texelColor = texture2D(texture0, fragTexCoord);
|
vec4 texelColor = texture2D(texture0, fragTexCoord);
|
||||||
|
|
||||||
// Calculate final fragment color
|
// Calculate final fragment color
|
||||||
gl_FragColor = texelColor*colDiffuse*fragColor;
|
gl_FragColor = texelColor*colDiffuse*fragColor;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ void main()
|
||||||
int boneIndex1 = int(vertexBoneIndices.y);
|
int boneIndex1 = int(vertexBoneIndices.y);
|
||||||
int boneIndex2 = int(vertexBoneIndices.z);
|
int boneIndex2 = int(vertexBoneIndices.z);
|
||||||
int boneIndex3 = int(vertexBoneIndices.w);
|
int boneIndex3 = int(vertexBoneIndices.w);
|
||||||
|
|
||||||
// WARNING: OpenGL ES 2.0 does not support automatic matrix transposing, neither transpose() function
|
// WARNING: OpenGL ES 2.0 does not support automatic matrix transposing, neither transpose() function
|
||||||
mat4 boneMatrixTransposed0 = mat4(
|
mat4 boneMatrixTransposed0 = mat4(
|
||||||
vec4(boneMatrices[boneIndex0][0].x, boneMatrices[boneIndex0][1].x, boneMatrices[boneIndex0][2].x, boneMatrices[boneIndex0][3].x),
|
vec4(boneMatrices[boneIndex0][0].x, boneMatrices[boneIndex0][1].x, boneMatrices[boneIndex0][2].x, boneMatrices[boneIndex0][3].x),
|
||||||
|
|
@ -45,13 +45,13 @@ void main()
|
||||||
vec4(boneMatrices[boneIndex3][0].y, boneMatrices[boneIndex3][1].y, boneMatrices[boneIndex3][2].y, boneMatrices[boneIndex3][3].y),
|
vec4(boneMatrices[boneIndex3][0].y, boneMatrices[boneIndex3][1].y, boneMatrices[boneIndex3][2].y, boneMatrices[boneIndex3][3].y),
|
||||||
vec4(boneMatrices[boneIndex3][0].z, boneMatrices[boneIndex3][1].z, boneMatrices[boneIndex3][2].z, boneMatrices[boneIndex3][3].z),
|
vec4(boneMatrices[boneIndex3][0].z, boneMatrices[boneIndex3][1].z, boneMatrices[boneIndex3][2].z, boneMatrices[boneIndex3][3].z),
|
||||||
vec4(boneMatrices[boneIndex3][0].w, boneMatrices[boneIndex3][1].w, boneMatrices[boneIndex3][2].w, boneMatrices[boneIndex3][3].w));
|
vec4(boneMatrices[boneIndex3][0].w, boneMatrices[boneIndex3][1].w, boneMatrices[boneIndex3][2].w, boneMatrices[boneIndex3][3].w));
|
||||||
|
|
||||||
vec4 skinnedPosition =
|
vec4 skinnedPosition =
|
||||||
vertexBoneWeights.x*(boneMatrixTransposed0*vec4(vertexPosition, 1.0)) +
|
vertexBoneWeights.x*(boneMatrixTransposed0*vec4(vertexPosition, 1.0)) +
|
||||||
vertexBoneWeights.y*(boneMatrixTransposed1*vec4(vertexPosition, 1.0)) +
|
vertexBoneWeights.y*(boneMatrixTransposed1*vec4(vertexPosition, 1.0)) +
|
||||||
vertexBoneWeights.z*(boneMatrixTransposed2*vec4(vertexPosition, 1.0)) +
|
vertexBoneWeights.z*(boneMatrixTransposed2*vec4(vertexPosition, 1.0)) +
|
||||||
vertexBoneWeights.w*(boneMatrixTransposed3*vec4(vertexPosition, 1.0));
|
vertexBoneWeights.w*(boneMatrixTransposed3*vec4(vertexPosition, 1.0));
|
||||||
|
|
||||||
fragTexCoord = vertexTexCoord;
|
fragTexCoord = vertexTexCoord;
|
||||||
fragColor = vertexColor;
|
fragColor = vertexColor;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ void main()
|
||||||
{
|
{
|
||||||
// Fetch color from texture sampler
|
// Fetch color from texture sampler
|
||||||
vec4 texelColor = texture2D(texture0, fragTexCoord);
|
vec4 texelColor = texture2D(texture0, fragTexCoord);
|
||||||
|
|
||||||
// Calculate final fragment color
|
// Calculate final fragment color
|
||||||
gl_FragColor = texelColor*colDiffuse*fragColor;
|
gl_FragColor = texelColor*colDiffuse*fragColor;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ void main()
|
||||||
int boneIndex1 = int(vertexBoneIndices.y);
|
int boneIndex1 = int(vertexBoneIndices.y);
|
||||||
int boneIndex2 = int(vertexBoneIndices.z);
|
int boneIndex2 = int(vertexBoneIndices.z);
|
||||||
int boneIndex3 = int(vertexBoneIndices.w);
|
int boneIndex3 = int(vertexBoneIndices.w);
|
||||||
|
|
||||||
// WARNING: OpenGL ES 2.0 does not support automatic matrix transposing, neither transpose() function
|
// WARNING: OpenGL ES 2.0 does not support automatic matrix transposing, neither transpose() function
|
||||||
mat4 boneMatrixTransposed0 = mat4(
|
mat4 boneMatrixTransposed0 = mat4(
|
||||||
vec4(boneMatrices[boneIndex0][0].x, boneMatrices[boneIndex0][1].x, boneMatrices[boneIndex0][2].x, boneMatrices[boneIndex0][3].x),
|
vec4(boneMatrices[boneIndex0][0].x, boneMatrices[boneIndex0][1].x, boneMatrices[boneIndex0][2].x, boneMatrices[boneIndex0][3].x),
|
||||||
|
|
@ -45,13 +45,13 @@ void main()
|
||||||
vec4(boneMatrices[boneIndex3][0].y, boneMatrices[boneIndex3][1].y, boneMatrices[boneIndex3][2].y, boneMatrices[boneIndex3][3].y),
|
vec4(boneMatrices[boneIndex3][0].y, boneMatrices[boneIndex3][1].y, boneMatrices[boneIndex3][2].y, boneMatrices[boneIndex3][3].y),
|
||||||
vec4(boneMatrices[boneIndex3][0].z, boneMatrices[boneIndex3][1].z, boneMatrices[boneIndex3][2].z, boneMatrices[boneIndex3][3].z),
|
vec4(boneMatrices[boneIndex3][0].z, boneMatrices[boneIndex3][1].z, boneMatrices[boneIndex3][2].z, boneMatrices[boneIndex3][3].z),
|
||||||
vec4(boneMatrices[boneIndex3][0].w, boneMatrices[boneIndex3][1].w, boneMatrices[boneIndex3][2].w, boneMatrices[boneIndex3][3].w));
|
vec4(boneMatrices[boneIndex3][0].w, boneMatrices[boneIndex3][1].w, boneMatrices[boneIndex3][2].w, boneMatrices[boneIndex3][3].w));
|
||||||
|
|
||||||
vec4 skinnedPosition =
|
vec4 skinnedPosition =
|
||||||
vertexBoneWeights.x*(boneMatrixTransposed0*vec4(vertexPosition, 1.0)) +
|
vertexBoneWeights.x*(boneMatrixTransposed0*vec4(vertexPosition, 1.0)) +
|
||||||
vertexBoneWeights.y*(boneMatrixTransposed1*vec4(vertexPosition, 1.0)) +
|
vertexBoneWeights.y*(boneMatrixTransposed1*vec4(vertexPosition, 1.0)) +
|
||||||
vertexBoneWeights.z*(boneMatrixTransposed2*vec4(vertexPosition, 1.0)) +
|
vertexBoneWeights.z*(boneMatrixTransposed2*vec4(vertexPosition, 1.0)) +
|
||||||
vertexBoneWeights.w*(boneMatrixTransposed3*vec4(vertexPosition, 1.0));
|
vertexBoneWeights.w*(boneMatrixTransposed3*vec4(vertexPosition, 1.0));
|
||||||
|
|
||||||
fragTexCoord = vertexTexCoord;
|
fragTexCoord = vertexTexCoord;
|
||||||
fragColor = vertexColor;
|
fragColor = vertexColor;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,17 +26,17 @@ void main()
|
||||||
int boneIndex1 = int(vertexBoneIndices.y);
|
int boneIndex1 = int(vertexBoneIndices.y);
|
||||||
int boneIndex2 = int(vertexBoneIndices.z);
|
int boneIndex2 = int(vertexBoneIndices.z);
|
||||||
int boneIndex3 = int(vertexBoneIndices.w);
|
int boneIndex3 = int(vertexBoneIndices.w);
|
||||||
|
|
||||||
vec4 skinnedPosition =
|
vec4 skinnedPosition =
|
||||||
vertexBoneWeights.x*(boneMatrices[boneIndex0]*vec4(vertexPosition, 1.0)) +
|
vertexBoneWeights.x*(boneMatrices[boneIndex0]*vec4(vertexPosition, 1.0)) +
|
||||||
vertexBoneWeights.y*(boneMatrices[boneIndex1]*vec4(vertexPosition, 1.0)) +
|
vertexBoneWeights.y*(boneMatrices[boneIndex1]*vec4(vertexPosition, 1.0)) +
|
||||||
vertexBoneWeights.z*(boneMatrices[boneIndex2]*vec4(vertexPosition, 1.0)) +
|
vertexBoneWeights.z*(boneMatrices[boneIndex2]*vec4(vertexPosition, 1.0)) +
|
||||||
vertexBoneWeights.w*(boneMatrices[boneIndex3]*vec4(vertexPosition, 1.0));
|
vertexBoneWeights.w*(boneMatrices[boneIndex3]*vec4(vertexPosition, 1.0));
|
||||||
|
|
||||||
vec4 skinnedNormal =
|
vec4 skinnedNormal =
|
||||||
vertexBoneWeights.x*(boneMatrices[boneIndex0]*vec4(vertexNormal, 0.0)) +
|
vertexBoneWeights.x*(boneMatrices[boneIndex0]*vec4(vertexNormal, 0.0)) +
|
||||||
vertexBoneWeights.y*(boneMatrices[boneIndex1]*vec4(vertexNormal, 0.0)) +
|
vertexBoneWeights.y*(boneMatrices[boneIndex1]*vec4(vertexNormal, 0.0)) +
|
||||||
vertexBoneWeights.z*(boneMatrices[boneIndex2]*vec4(vertexNormal, 0.0)) +
|
vertexBoneWeights.z*(boneMatrices[boneIndex2]*vec4(vertexNormal, 0.0)) +
|
||||||
vertexBoneWeights.w*(boneMatrices[boneIndex3]*vec4(vertexNormal, 0.0));
|
vertexBoneWeights.w*(boneMatrices[boneIndex3]*vec4(vertexNormal, 0.0));
|
||||||
skinnedNormal.w = 0.0;
|
skinnedNormal.w = 0.0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,12 +58,12 @@ void main()
|
||||||
float gray = GreyScale(cellColor);
|
float gray = GreyScale(cellColor);
|
||||||
|
|
||||||
float n = 4096.0;
|
float n = 4096.0;
|
||||||
|
|
||||||
// Character set from https://www.shadertoy.com/view/lssGDj
|
// Character set from https://www.shadertoy.com/view/lssGDj
|
||||||
// Create new bitmaps https://thrill-project.com/archiv/coding/bitmap/
|
// Create new bitmaps https://thrill-project.com/archiv/coding/bitmap/
|
||||||
if (gray > 0.2) n = 65600.0; // :
|
if (gray > 0.2) n = 65600.0; // :
|
||||||
if (gray > 0.3) n = 18725316.0; // v
|
if (gray > 0.3) n = 18725316.0; // v
|
||||||
if (gray > 0.4) n = 15255086.0; // o
|
if (gray > 0.4) n = 15255086.0; // o
|
||||||
if (gray > 0.5) n = 13121101.0; // &
|
if (gray > 0.5) n = 13121101.0; // &
|
||||||
if (gray > 0.6) n = 15252014.0; // 8
|
if (gray > 0.6) n = 15252014.0; // 8
|
||||||
if (gray > 0.7) n = 13195790.0; // @
|
if (gray > 0.7) n = 13195790.0; // @
|
||||||
|
|
|
||||||
|
|
@ -12,5 +12,5 @@ void main()
|
||||||
fragTexCoord = vertexTexCoord;
|
fragTexCoord = vertexTexCoord;
|
||||||
|
|
||||||
// Calculate final vertex position
|
// Calculate final vertex position
|
||||||
gl_Position = vec4(vertexPosition, 1.0);
|
gl_Position = vec4(vertexPosition, 1.0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#version 100
|
#version 100
|
||||||
#extension GL_EXT_frag_depth : enable
|
#extension GL_EXT_frag_depth : enable
|
||||||
|
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
|
|
||||||
|
|
@ -14,7 +14,7 @@ uniform vec4 colDiffuse;
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec4 texelColor = texture2D(texture0, fragTexCoord);
|
vec4 texelColor = texture2D(texture0, fragTexCoord);
|
||||||
|
|
||||||
gl_FragColor = texelColor*colDiffuse*fragColor;
|
gl_FragColor = texelColor*colDiffuse*fragColor;
|
||||||
gl_FragDepthEXT = 1.0 - gl_FragCoord.z;
|
gl_FragDepthEXT = 1.0 - gl_FragCoord.z;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,13 +24,13 @@ void main()
|
||||||
{
|
{
|
||||||
// Store the fragment position vector in the first gbuffer texture
|
// Store the fragment position vector in the first gbuffer texture
|
||||||
//gPosition = fragPosition;
|
//gPosition = fragPosition;
|
||||||
|
|
||||||
// Store the per-fragment normals into the gbuffer
|
// Store the per-fragment normals into the gbuffer
|
||||||
//gNormal = normalize(fragNormal);
|
//gNormal = normalize(fragNormal);
|
||||||
|
|
||||||
// Store the diffuse per-fragment color
|
// Store the diffuse per-fragment color
|
||||||
gl_FragColor.rgb = texture2D(texture0, fragTexCoord).rgb;
|
gl_FragColor.rgb = texture2D(texture0, fragTexCoord).rgb;
|
||||||
|
|
||||||
// Store specular intensity in gAlbedoSpec's alpha component
|
// Store specular intensity in gAlbedoSpec's alpha component
|
||||||
gl_FragColor.a = texture2D(specularTexture, fragTexCoord).r;
|
gl_FragColor.a = texture2D(specularTexture, fragTexCoord).r;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ void main()
|
||||||
{
|
{
|
||||||
// Calculate vertex attributes for fragment shader
|
// Calculate vertex attributes for fragment shader
|
||||||
vec4 worldPos = matModel*vec4(vertexPosition, 1.0);
|
vec4 worldPos = matModel*vec4(vertexPosition, 1.0);
|
||||||
fragPosition = worldPos.xyz;
|
fragPosition = worldPos.xyz;
|
||||||
fragTexCoord = vertexTexCoord;
|
fragTexCoord = vertexTexCoord;
|
||||||
fragColor = vertexColor;
|
fragColor = vertexColor;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#version 100
|
#version 100
|
||||||
|
|
||||||
#extension GL_EXT_frag_depth : enable // Extension required for writing depth
|
#extension GL_EXT_frag_depth : enable // Extension required for writing depth
|
||||||
|
|
||||||
precision mediump float; // Precision required for OpenGL ES2 (WebGL)
|
precision mediump float; // Precision required for OpenGL ES2 (WebGL)
|
||||||
|
|
||||||
varying vec2 fragTexCoord;
|
varying vec2 fragTexCoord;
|
||||||
|
|
|
||||||
|
|
@ -32,12 +32,12 @@ float sdHorseshoe(in vec3 p, in vec2 c, in float r, in float le, vec2 w)
|
||||||
{
|
{
|
||||||
p.x = abs(p.x);
|
p.x = abs(p.x);
|
||||||
float l = length(p.xy);
|
float l = length(p.xy);
|
||||||
p.xy = mat2(-c.x, c.y,
|
p.xy = mat2(-c.x, c.y,
|
||||||
c.y, c.x)*p.xy;
|
c.y, c.x)*p.xy;
|
||||||
p.xy = vec2((p.y>0.0 || p.x>0.0)?p.x:l*sign(-c.x),
|
p.xy = vec2((p.y>0.0 || p.x>0.0)?p.x:l*sign(-c.x),
|
||||||
(p.x>0.0)?p.y:l);
|
(p.x>0.0)?p.y:l);
|
||||||
p.xy = vec2(p.x,abs(p.y-r))-vec2(le,0.0);
|
p.xy = vec2(p.x,abs(p.y-r))-vec2(le,0.0);
|
||||||
|
|
||||||
vec2 q = vec2(length(max(p.xy,0.0)) + min(0.0,max(p.x,p.y)),p.z);
|
vec2 q = vec2(length(max(p.xy,0.0)) + min(0.0,max(p.x,p.y)),p.z);
|
||||||
vec2 d = abs(q) - w;
|
vec2 d = abs(q) - w;
|
||||||
return min(max(d.x,d.y),0.0) + length(max(d,0.0));
|
return min(max(d.x,d.y),0.0) + length(max(d,0.0));
|
||||||
|
|
@ -56,9 +56,9 @@ float sdSixWayCutHollowSphere(vec3 p, float r, float h, float t)
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 q = vec2(length(ap.yz), ap.x);
|
vec2 q = vec2(length(ap.yz), ap.x);
|
||||||
|
|
||||||
float w = sqrt(r*r-h*h);
|
float w = sqrt(r*r-h*h);
|
||||||
|
|
||||||
return ((h*q.x<w*q.y) ? length(q-vec2(w,h)) : abs(length(q)-r)) - t;
|
return ((h*q.x<w*q.y) ? length(q-vec2(w,h)) : abs(length(q)-r)) - t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,8 +110,8 @@ vec2 raycast(in vec3 ro, in vec3 rd)
|
||||||
if (t>tmax) break;
|
if (t>tmax) break;
|
||||||
vec2 h = map(ro+rd*t);
|
vec2 h = map(ro+rd*t);
|
||||||
if (abs(h.x) < (0.0001*t))
|
if (abs(h.x) < (0.0001*t))
|
||||||
{
|
{
|
||||||
res = vec2(t,h.y);
|
res = vec2(t,h.y);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
t += h.x;
|
t += h.x;
|
||||||
|
|
@ -146,9 +146,9 @@ float calcSoftshadow(in vec3 ro, in vec3 rd, in float mint, in float tmax)
|
||||||
vec3 calcNormal(in vec3 pos)
|
vec3 calcNormal(in vec3 pos)
|
||||||
{
|
{
|
||||||
vec2 e = vec2(1.0,-1.0)*0.5773*0.0005;
|
vec2 e = vec2(1.0,-1.0)*0.5773*0.0005;
|
||||||
return normalize(e.xyy*map(pos + e.xyy).x +
|
return normalize(e.xyy*map(pos + e.xyy).x +
|
||||||
e.yyx*map(pos + e.yyx).x +
|
e.yyx*map(pos + e.yyx).x +
|
||||||
e.yxy*map(pos + e.yxy).x +
|
e.yxy*map(pos + e.yxy).x +
|
||||||
e.xxx*map(pos + e.xxx).x);
|
e.xxx*map(pos + e.xxx).x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -176,15 +176,15 @@ float checkersGradBox(in vec2 p)
|
||||||
// analytical integral (box filter)
|
// analytical integral (box filter)
|
||||||
vec2 i = 2.0*(abs(fract((p-0.5*w)*0.5)-0.5)-abs(fract((p+0.5*w)*0.5)-0.5))/w;
|
vec2 i = 2.0*(abs(fract((p-0.5*w)*0.5)-0.5)-abs(fract((p+0.5*w)*0.5)-0.5))/w;
|
||||||
// xor pattern
|
// xor pattern
|
||||||
return 0.5 - 0.5*i.x*i.y;
|
return 0.5 - 0.5*i.x*i.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.shadertoy.com/view/tdS3DG
|
// https://www.shadertoy.com/view/tdS3DG
|
||||||
vec4 render(in vec3 ro, in vec3 rd)
|
vec4 render(in vec3 ro, in vec3 rd)
|
||||||
{
|
{
|
||||||
// background
|
// background
|
||||||
vec3 col = vec3(0.7, 0.7, 0.9) - max(rd.y,0.0)*0.3;
|
vec3 col = vec3(0.7, 0.7, 0.9) - max(rd.y,0.0)*0.3;
|
||||||
|
|
||||||
// raycast scene
|
// raycast scene
|
||||||
vec2 res = raycast(ro,rd);
|
vec2 res = raycast(ro,rd);
|
||||||
float t = res.x;
|
float t = res.x;
|
||||||
|
|
@ -194,11 +194,11 @@ vec4 render(in vec3 ro, in vec3 rd)
|
||||||
vec3 pos = ro + t*rd;
|
vec3 pos = ro + t*rd;
|
||||||
vec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal(pos);
|
vec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal(pos);
|
||||||
vec3 ref = reflect(rd, nor);
|
vec3 ref = reflect(rd, nor);
|
||||||
|
|
||||||
// material
|
// material
|
||||||
col = 0.2 + 0.2*sin(m*2.0 + vec3(0.0,1.0,2.0));
|
col = 0.2 + 0.2*sin(m*2.0 + vec3(0.0,1.0,2.0));
|
||||||
float ks = 1.0;
|
float ks = 1.0;
|
||||||
|
|
||||||
if (m<1.5)
|
if (m<1.5)
|
||||||
{
|
{
|
||||||
float f = checkersGradBox(3.0*pos.xz);
|
float f = checkersGradBox(3.0*pos.xz);
|
||||||
|
|
@ -208,7 +208,7 @@ vec4 render(in vec3 ro, in vec3 rd)
|
||||||
|
|
||||||
// lighting
|
// lighting
|
||||||
float occ = calcAO(pos, nor);
|
float occ = calcAO(pos, nor);
|
||||||
|
|
||||||
vec3 lin = vec3(0.0);
|
vec3 lin = vec3(0.0);
|
||||||
|
|
||||||
// sun
|
// sun
|
||||||
|
|
@ -249,7 +249,7 @@ vec4 render(in vec3 ro, in vec3 rd)
|
||||||
dif *= occ;
|
dif *= occ;
|
||||||
lin += col*0.25*dif*vec3(1.00,1.00,1.00);
|
lin += col*0.25*dif*vec3(1.00,1.00,1.00);
|
||||||
}
|
}
|
||||||
|
|
||||||
col = lin;
|
col = lin;
|
||||||
|
|
||||||
col = mix(col, vec3(0.7,0.7,0.9), 1.0-exp(-0.0001*t*t*t));
|
col = mix(col, vec3(0.7,0.7,0.9), 1.0-exp(-0.0001*t*t*t));
|
||||||
|
|
@ -289,7 +289,7 @@ void main()
|
||||||
color = res.xyz;
|
color = res.xyz;
|
||||||
depth = CalcDepth(rd,res.w);
|
depth = CalcDepth(rd,res.w);
|
||||||
}
|
}
|
||||||
|
|
||||||
gl_FragColor = vec4(color , 1.0);
|
gl_FragColor = vec4(color , 1.0);
|
||||||
gl_FragDepthEXT = depth;
|
gl_FragDepthEXT = depth;
|
||||||
}
|
}
|
||||||
|
|
@ -48,7 +48,7 @@ void main()
|
||||||
float normR = float(iter - (iter/55)*55)/55.0;
|
float normR = float(iter - (iter/55)*55)/55.0;
|
||||||
float normG = float(iter - (iter/69)*69)/69.0;
|
float normG = float(iter - (iter/69)*69)/69.0;
|
||||||
float normB = float(iter - (iter/40)*40)/40.0;
|
float normB = float(iter - (iter/40)*40)/40.0;
|
||||||
|
|
||||||
gl_FragColor = vec4(sin(normR*PI), sin(normG*PI), sin(normB*PI), 1.0);
|
gl_FragColor = vec4(sin(normR*PI), sin(normG*PI), sin(normB*PI), 1.0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ void main()
|
||||||
|
|
||||||
float specCo = 0.0;
|
float specCo = 0.0;
|
||||||
|
|
||||||
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent); // 16 refers to shine
|
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent);
|
||||||
|
|
||||||
specular += specCo;
|
specular += specCo;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ void main()
|
||||||
// Convert the (normalized) texel color RED component (GB would work, too)
|
// Convert the (normalized) texel color RED component (GB would work, too)
|
||||||
// to the palette index by scaling up from [0..1] to [0..255]
|
// to the palette index by scaling up from [0..1] to [0..255]
|
||||||
int index = int(texelColor.r*255.0);
|
int index = int(texelColor.r*255.0);
|
||||||
|
|
||||||
ivec3 color = ivec3(0);
|
ivec3 color = ivec3(0);
|
||||||
|
|
||||||
// NOTE: On GLSL 100 we are not allowed to index a uniform array by a variable value,
|
// NOTE: On GLSL 100 we are not allowed to index a uniform array by a variable value,
|
||||||
|
|
@ -34,7 +34,7 @@ void main()
|
||||||
else if (index == 5) color = palette[5];
|
else if (index == 5) color = palette[5];
|
||||||
else if (index == 6) color = palette[6];
|
else if (index == 6) color = palette[6];
|
||||||
else if (index == 7) color = palette[7];
|
else if (index == 7) color = palette[7];
|
||||||
|
|
||||||
//gl_FragColor = texture2D(palette, texelColor.xy); // Alternative to ivec3
|
//gl_FragColor = texture2D(palette, texelColor.xy); // Alternative to ivec3
|
||||||
|
|
||||||
// Calculate final fragment color. Note that the palette color components
|
// Calculate final fragment color. Note that the palette color components
|
||||||
|
|
|
||||||
|
|
@ -83,11 +83,11 @@ vec3 ComputePBR()
|
||||||
{
|
{
|
||||||
vec3 albedo = texture2D(albedoMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb;
|
vec3 albedo = texture2D(albedoMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb;
|
||||||
albedo = vec3(albedoColor.x*albedo.x, albedoColor.y*albedo.y, albedoColor.z*albedo.z);
|
albedo = vec3(albedoColor.x*albedo.x, albedoColor.y*albedo.y, albedoColor.z*albedo.z);
|
||||||
|
|
||||||
float metallic = clamp(metallicValue, 0.0, 1.0);
|
float metallic = clamp(metallicValue, 0.0, 1.0);
|
||||||
float roughness = clamp(roughnessValue, 0.0, 1.0);
|
float roughness = clamp(roughnessValue, 0.0, 1.0);
|
||||||
float ao = clamp(aoValue, 0.0, 1.0);
|
float ao = clamp(aoValue, 0.0, 1.0);
|
||||||
|
|
||||||
if (useTexMRA == 1)
|
if (useTexMRA == 1)
|
||||||
{
|
{
|
||||||
vec4 mra = texture2D(mraMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y));
|
vec4 mra = texture2D(mraMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y));
|
||||||
|
|
@ -132,18 +132,18 @@ vec3 ComputePBR()
|
||||||
vec3 F = SchlickFresnel(hDotV, baseRefl); // Fresnel proportion of specular reflectance
|
vec3 F = SchlickFresnel(hDotV, baseRefl); // Fresnel proportion of specular reflectance
|
||||||
|
|
||||||
vec3 spec = (D*G*F)/(4.0*nDotV*nDotL);
|
vec3 spec = (D*G*F)/(4.0*nDotV*nDotL);
|
||||||
|
|
||||||
// Difuse and spec light can't be above 1.0
|
// Difuse and spec light can't be above 1.0
|
||||||
// kD = 1.0 - kS diffuse component is equal 1.0 - spec comonent
|
// kD = 1.0 - kS diffuse component is equal 1.0 - spec comonent
|
||||||
vec3 kD = vec3(1.0) - F;
|
vec3 kD = vec3(1.0) - F;
|
||||||
|
|
||||||
// Mult kD by the inverse of metallnes, only non-metals should have diffuse light
|
// Mult kD by the inverse of metallnes, only non-metals should have diffuse light
|
||||||
kD *= 1.0 - metallic;
|
kD *= 1.0 - metallic;
|
||||||
lightAccum += ((kD*albedo.rgb/PI + spec)*radiance*nDotL)*float(lights[i].enabled); // Angle of light has impact on result
|
lightAccum += ((kD*albedo.rgb/PI + spec)*radiance*nDotL)*float(lights[i].enabled); // Angle of light has impact on result
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 ambientFinal = (ambientColor + albedo)*ambient*0.5;
|
vec3 ambientFinal = (ambientColor + albedo)*ambient*0.5;
|
||||||
|
|
||||||
return (ambientFinal + lightAccum*ao + emissive);
|
return (ambientFinal + lightAccum*ao + emissive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -153,7 +153,7 @@ void main()
|
||||||
|
|
||||||
// HDR tonemapping
|
// HDR tonemapping
|
||||||
color = pow(color, color + vec3(1.0));
|
color = pow(color, color + vec3(1.0));
|
||||||
|
|
||||||
// Gamma correction
|
// Gamma correction
|
||||||
color = pow(color, vec3(1.0/2.2));
|
color = pow(color, vec3(1.0/2.2));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ void main()
|
||||||
float bias = max(0.0008*(1.0 - dot(normal, l)), 0.00008);
|
float bias = max(0.0008*(1.0 - dot(normal, l)), 0.00008);
|
||||||
int shadowCounter = 0;
|
int shadowCounter = 0;
|
||||||
const int numSamples = 9;
|
const int numSamples = 9;
|
||||||
|
|
||||||
// PCF (percentage-closer filtering) algorithm:
|
// PCF (percentage-closer filtering) algorithm:
|
||||||
// Instead of testing if just one point is closer to the current point,
|
// Instead of testing if just one point is closer to the current point,
|
||||||
// we test the surrounding points as well
|
// we test the surrounding points as well
|
||||||
|
|
@ -74,7 +74,7 @@ void main()
|
||||||
if (curDepth - bias > sampleDepth) shadowCounter++;
|
if (curDepth - bias > sampleDepth) shadowCounter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
finalColor = mix(finalColor, vec4(0, 0, 0, 1), float(shadowCounter)/float(numSamples));
|
finalColor = mix(finalColor, vec4(0, 0, 0, 1), float(shadowCounter)/float(numSamples));
|
||||||
|
|
||||||
// Add ambient lighting whether in shadow or not
|
// Add ambient lighting whether in shadow or not
|
||||||
|
|
|
||||||
|
|
@ -56,12 +56,12 @@ void main()
|
||||||
float gray = GreyScale(cellColor);
|
float gray = GreyScale(cellColor);
|
||||||
|
|
||||||
float n = 4096.0;
|
float n = 4096.0;
|
||||||
|
|
||||||
// Character set from https://www.shadertoy.com/view/lssGDj
|
// Character set from https://www.shadertoy.com/view/lssGDj
|
||||||
// Create new bitmaps https://thrill-project.com/archiv/coding/bitmap/
|
// Create new bitmaps https://thrill-project.com/archiv/coding/bitmap/
|
||||||
if (gray > 0.2) n = 65600.0; // :
|
if (gray > 0.2) n = 65600.0; // :
|
||||||
if (gray > 0.3) n = 18725316.0; // v
|
if (gray > 0.3) n = 18725316.0; // v
|
||||||
if (gray > 0.4) n = 15255086.0; // o
|
if (gray > 0.4) n = 15255086.0; // o
|
||||||
if (gray > 0.5) n = 13121101.0; // &
|
if (gray > 0.5) n = 13121101.0; // &
|
||||||
if (gray > 0.6) n = 15252014.0; // 8
|
if (gray > 0.6) n = 15252014.0; // 8
|
||||||
if (gray > 0.7) n = 13195790.0; // @
|
if (gray > 0.7) n = 13195790.0; // @
|
||||||
|
|
|
||||||
|
|
@ -12,5 +12,5 @@ void main()
|
||||||
fragTexCoord = vertexTexCoord;
|
fragTexCoord = vertexTexCoord;
|
||||||
|
|
||||||
// Calculate final vertex position
|
// Calculate final vertex position
|
||||||
gl_Position = vec4(vertexPosition, 1.0);
|
gl_Position = vec4(vertexPosition, 1.0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#version 120
|
#version 120
|
||||||
|
|
||||||
#extension GL_EXT_frag_depth : enable
|
#extension GL_EXT_frag_depth : enable
|
||||||
|
|
||||||
varying vec2 fragTexCoord;
|
varying vec2 fragTexCoord;
|
||||||
varying vec4 fragColor;
|
varying vec4 fragColor;
|
||||||
|
|
@ -11,7 +11,7 @@ uniform vec4 colDiffuse;
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec4 texelColor = texture2D(texture0, fragTexCoord);
|
vec4 texelColor = texture2D(texture0, fragTexCoord);
|
||||||
|
|
||||||
gl_FragColor = texelColor*colDiffuse*fragColor;
|
gl_FragColor = texelColor*colDiffuse*fragColor;
|
||||||
gl_FragDepthEXT = 1.0 - gl_FragCoord.z;
|
gl_FragDepthEXT = 1.0 - gl_FragCoord.z;
|
||||||
}
|
}
|
||||||
|
|
@ -22,13 +22,13 @@ void main()
|
||||||
{
|
{
|
||||||
// Store the fragment position vector in the first gbuffer texture
|
// Store the fragment position vector in the first gbuffer texture
|
||||||
//gPosition = fragPosition;
|
//gPosition = fragPosition;
|
||||||
|
|
||||||
// Store the per-fragment normals into the gbuffer
|
// Store the per-fragment normals into the gbuffer
|
||||||
//gNormal = normalize(fragNormal);
|
//gNormal = normalize(fragNormal);
|
||||||
|
|
||||||
// Store the diffuse per-fragment color
|
// Store the diffuse per-fragment color
|
||||||
gl_FragColor.rgb = texture2D(texture0, fragTexCoord).rgb;
|
gl_FragColor.rgb = texture2D(texture0, fragTexCoord).rgb;
|
||||||
|
|
||||||
// Store specular intensity in gAlbedoSpec's alpha component
|
// Store specular intensity in gAlbedoSpec's alpha component
|
||||||
gl_FragColor.a = texture2D(specularTexture, fragTexCoord).r;
|
gl_FragColor.a = texture2D(specularTexture, fragTexCoord).r;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ void main()
|
||||||
{
|
{
|
||||||
// Calculate vertex attributes for fragment shader
|
// Calculate vertex attributes for fragment shader
|
||||||
vec4 worldPos = matModel*vec4(vertexPosition, 1.0);
|
vec4 worldPos = matModel*vec4(vertexPosition, 1.0);
|
||||||
fragPosition = worldPos.xyz;
|
fragPosition = worldPos.xyz;
|
||||||
fragTexCoord = vertexTexCoord;
|
fragTexCoord = vertexTexCoord;
|
||||||
fragColor = vertexColor;
|
fragColor = vertexColor;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#version 120
|
#version 120
|
||||||
|
|
||||||
#extension GL_EXT_frag_depth : enable // Extension required for writing depth
|
#extension GL_EXT_frag_depth : enable // Extension required for writing depth
|
||||||
|
|
||||||
varying vec2 fragTexCoord;
|
varying vec2 fragTexCoord;
|
||||||
varying vec4 fragColor;
|
varying vec4 fragColor;
|
||||||
|
|
|
||||||
|
|
@ -30,12 +30,12 @@ float sdHorseshoe(in vec3 p, in vec2 c, in float r, in float le, vec2 w)
|
||||||
{
|
{
|
||||||
p.x = abs(p.x);
|
p.x = abs(p.x);
|
||||||
float l = length(p.xy);
|
float l = length(p.xy);
|
||||||
p.xy = mat2(-c.x, c.y,
|
p.xy = mat2(-c.x, c.y,
|
||||||
c.y, c.x)*p.xy;
|
c.y, c.x)*p.xy;
|
||||||
p.xy = vec2((p.y>0.0 || p.x>0.0)?p.x:l*sign(-c.x),
|
p.xy = vec2((p.y>0.0 || p.x>0.0)?p.x:l*sign(-c.x),
|
||||||
(p.x>0.0)?p.y:l);
|
(p.x>0.0)?p.y:l);
|
||||||
p.xy = vec2(p.x,abs(p.y-r))-vec2(le,0.0);
|
p.xy = vec2(p.x,abs(p.y-r))-vec2(le,0.0);
|
||||||
|
|
||||||
vec2 q = vec2(length(max(p.xy,0.0)) + min(0.0,max(p.x,p.y)),p.z);
|
vec2 q = vec2(length(max(p.xy,0.0)) + min(0.0,max(p.x,p.y)),p.z);
|
||||||
vec2 d = abs(q) - w;
|
vec2 d = abs(q) - w;
|
||||||
return min(max(d.x,d.y),0.0) + length(max(d,0.0));
|
return min(max(d.x,d.y),0.0) + length(max(d,0.0));
|
||||||
|
|
@ -54,9 +54,9 @@ float sdSixWayCutHollowSphere(vec3 p, float r, float h, float t)
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 q = vec2(length(ap.yz), ap.x);
|
vec2 q = vec2(length(ap.yz), ap.x);
|
||||||
|
|
||||||
float w = sqrt(r*r-h*h);
|
float w = sqrt(r*r-h*h);
|
||||||
|
|
||||||
return ((h*q.x<w*q.y) ? length(q-vec2(w,h)) : abs(length(q)-r)) - t;
|
return ((h*q.x<w*q.y) ? length(q-vec2(w,h)) : abs(length(q)-r)) - t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,8 +108,8 @@ vec2 raycast(in vec3 ro, in vec3 rd)
|
||||||
if (t>tmax) break;
|
if (t>tmax) break;
|
||||||
vec2 h = map(ro+rd*t);
|
vec2 h = map(ro+rd*t);
|
||||||
if (abs(h.x) < (0.0001*t))
|
if (abs(h.x) < (0.0001*t))
|
||||||
{
|
{
|
||||||
res = vec2(t,h.y);
|
res = vec2(t,h.y);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
t += h.x;
|
t += h.x;
|
||||||
|
|
@ -144,9 +144,9 @@ float calcSoftshadow(in vec3 ro, in vec3 rd, in float mint, in float tmax)
|
||||||
vec3 calcNormal(in vec3 pos)
|
vec3 calcNormal(in vec3 pos)
|
||||||
{
|
{
|
||||||
vec2 e = vec2(1.0, -1.0)*0.5773*0.0005;
|
vec2 e = vec2(1.0, -1.0)*0.5773*0.0005;
|
||||||
return normalize(e.xyy*map(pos + e.xyy).x +
|
return normalize(e.xyy*map(pos + e.xyy).x +
|
||||||
e.yyx*map(pos + e.yyx).x +
|
e.yyx*map(pos + e.yyx).x +
|
||||||
e.yxy*map(pos + e.yxy).x +
|
e.yxy*map(pos + e.yxy).x +
|
||||||
e.xxx*map(pos + e.xxx).x);
|
e.xxx*map(pos + e.xxx).x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -174,15 +174,15 @@ float checkersGradBox(in vec2 p)
|
||||||
// analytical integral (box filter)
|
// analytical integral (box filter)
|
||||||
vec2 i = 2.0*(abs(fract((p-0.5*w)*0.5)-0.5)-abs(fract((p+0.5*w)*0.5)-0.5))/w;
|
vec2 i = 2.0*(abs(fract((p-0.5*w)*0.5)-0.5)-abs(fract((p+0.5*w)*0.5)-0.5))/w;
|
||||||
// xor pattern
|
// xor pattern
|
||||||
return 0.5 - 0.5*i.x*i.y;
|
return 0.5 - 0.5*i.x*i.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.shadertoy.com/view/tdS3DG
|
// https://www.shadertoy.com/view/tdS3DG
|
||||||
vec4 render(in vec3 ro, in vec3 rd)
|
vec4 render(in vec3 ro, in vec3 rd)
|
||||||
{
|
{
|
||||||
// background
|
// background
|
||||||
vec3 col = vec3(0.7, 0.7, 0.9) - max(rd.y,0.0)*0.3;
|
vec3 col = vec3(0.7, 0.7, 0.9) - max(rd.y,0.0)*0.3;
|
||||||
|
|
||||||
// raycast scene
|
// raycast scene
|
||||||
vec2 res = raycast(ro,rd);
|
vec2 res = raycast(ro,rd);
|
||||||
float t = res.x;
|
float t = res.x;
|
||||||
|
|
@ -192,11 +192,11 @@ vec4 render(in vec3 ro, in vec3 rd)
|
||||||
vec3 pos = ro + t*rd;
|
vec3 pos = ro + t*rd;
|
||||||
vec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal(pos);
|
vec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal(pos);
|
||||||
vec3 ref = reflect(rd, nor);
|
vec3 ref = reflect(rd, nor);
|
||||||
|
|
||||||
// material
|
// material
|
||||||
col = 0.2 + 0.2*sin(m*2.0 + vec3(0.0,1.0,2.0));
|
col = 0.2 + 0.2*sin(m*2.0 + vec3(0.0,1.0,2.0));
|
||||||
float ks = 1.0;
|
float ks = 1.0;
|
||||||
|
|
||||||
if (m<1.5)
|
if (m<1.5)
|
||||||
{
|
{
|
||||||
float f = checkersGradBox(3.0*pos.xz);
|
float f = checkersGradBox(3.0*pos.xz);
|
||||||
|
|
@ -206,7 +206,7 @@ vec4 render(in vec3 ro, in vec3 rd)
|
||||||
|
|
||||||
// lighting
|
// lighting
|
||||||
float occ = calcAO(pos, nor);
|
float occ = calcAO(pos, nor);
|
||||||
|
|
||||||
vec3 lin = vec3(0.0);
|
vec3 lin = vec3(0.0);
|
||||||
|
|
||||||
// sun
|
// sun
|
||||||
|
|
@ -247,7 +247,7 @@ vec4 render(in vec3 ro, in vec3 rd)
|
||||||
dif *= occ;
|
dif *= occ;
|
||||||
lin += col*0.25*dif*vec3(1.00,1.00,1.00);
|
lin += col*0.25*dif*vec3(1.00,1.00,1.00);
|
||||||
}
|
}
|
||||||
|
|
||||||
col = lin;
|
col = lin;
|
||||||
|
|
||||||
col = mix(col, vec3(0.7,0.7,0.9), 1.0-exp(-0.0001*t*t*t));
|
col = mix(col, vec3(0.7,0.7,0.9), 1.0-exp(-0.0001*t*t*t));
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ void main()
|
||||||
|
|
||||||
float specCo = 0.0;
|
float specCo = 0.0;
|
||||||
|
|
||||||
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent); // 16 refers to shine
|
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent);
|
||||||
|
|
||||||
specular += specCo;
|
specular += specCo;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,11 +81,11 @@ vec3 ComputePBR()
|
||||||
{
|
{
|
||||||
vec3 albedo = texture2D(albedoMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb;
|
vec3 albedo = texture2D(albedoMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb;
|
||||||
albedo = vec3(albedoColor.x*albedo.x, albedoColor.y*albedo.y, albedoColor.z*albedo.z);
|
albedo = vec3(albedoColor.x*albedo.x, albedoColor.y*albedo.y, albedoColor.z*albedo.z);
|
||||||
|
|
||||||
float metallic = clamp(metallicValue, 0.0, 1.0);
|
float metallic = clamp(metallicValue, 0.0, 1.0);
|
||||||
float roughness = clamp(roughnessValue, 0.0, 1.0);
|
float roughness = clamp(roughnessValue, 0.0, 1.0);
|
||||||
float ao = clamp(aoValue, 0.0, 1.0);
|
float ao = clamp(aoValue, 0.0, 1.0);
|
||||||
|
|
||||||
if (useTexMRA == 1)
|
if (useTexMRA == 1)
|
||||||
{
|
{
|
||||||
vec4 mra = texture2D(mraMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y));
|
vec4 mra = texture2D(mraMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y));
|
||||||
|
|
@ -130,18 +130,18 @@ vec3 ComputePBR()
|
||||||
vec3 F = SchlickFresnel(hDotV, baseRefl); // Fresnel proportion of specular reflectance
|
vec3 F = SchlickFresnel(hDotV, baseRefl); // Fresnel proportion of specular reflectance
|
||||||
|
|
||||||
vec3 spec = (D*G*F)/(4.0*nDotV*nDotL);
|
vec3 spec = (D*G*F)/(4.0*nDotV*nDotL);
|
||||||
|
|
||||||
// Difuse and spec light can't be above 1.0
|
// Difuse and spec light can't be above 1.0
|
||||||
// kD = 1.0 - kS diffuse component is equal 1.0 - spec comonent
|
// kD = 1.0 - kS diffuse component is equal 1.0 - spec comonent
|
||||||
vec3 kD = vec3(1.0) - F;
|
vec3 kD = vec3(1.0) - F;
|
||||||
|
|
||||||
// Mult kD by the inverse of metallnes, only non-metals should have diffuse light
|
// Mult kD by the inverse of metallnes, only non-metals should have diffuse light
|
||||||
kD *= 1.0 - metallic;
|
kD *= 1.0 - metallic;
|
||||||
lightAccum += ((kD*albedo.rgb/PI + spec)*radiance*nDotL)*float(lights[i].enabled); // Angle of light has impact on result
|
lightAccum += ((kD*albedo.rgb/PI + spec)*radiance*nDotL)*float(lights[i].enabled); // Angle of light has impact on result
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 ambientFinal = (ambientColor + albedo)*ambient*0.5;
|
vec3 ambientFinal = (ambientColor + albedo)*ambient*0.5;
|
||||||
|
|
||||||
return (ambientFinal + lightAccum*ao + emissive);
|
return (ambientFinal + lightAccum*ao + emissive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -151,7 +151,7 @@ void main()
|
||||||
|
|
||||||
// HDR tonemapping
|
// HDR tonemapping
|
||||||
color = pow(color, color + vec3(1.0));
|
color = pow(color, color + vec3(1.0));
|
||||||
|
|
||||||
// Gamma correction
|
// Gamma correction
|
||||||
color = pow(color, vec3(1.0/2.2));
|
color = pow(color, vec3(1.0/2.2));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ void main()
|
||||||
float bias = max(0.0008*(1.0 - dot(normal, l)), 0.00008);
|
float bias = max(0.0008*(1.0 - dot(normal, l)), 0.00008);
|
||||||
int shadowCounter = 0;
|
int shadowCounter = 0;
|
||||||
const int numSamples = 9;
|
const int numSamples = 9;
|
||||||
|
|
||||||
// PCF (percentage-closer filtering) algorithm:
|
// PCF (percentage-closer filtering) algorithm:
|
||||||
// Instead of testing if just one point is closer to the current point,
|
// Instead of testing if just one point is closer to the current point,
|
||||||
// we test the surrounding points as well
|
// we test the surrounding points as well
|
||||||
|
|
@ -72,7 +72,7 @@ void main()
|
||||||
if (curDepth - bias > sampleDepth) shadowCounter++;
|
if (curDepth - bias > sampleDepth) shadowCounter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
finalColor = mix(finalColor, vec4(0, 0, 0, 1), float(shadowCounter)/float(numSamples));
|
finalColor = mix(finalColor, vec4(0, 0, 0, 1), float(shadowCounter)/float(numSamples));
|
||||||
|
|
||||||
// Add ambient lighting whether in shadow or not
|
// Add ambient lighting whether in shadow or not
|
||||||
|
|
|
||||||
|
|
@ -52,12 +52,12 @@ void main()
|
||||||
float gray = GreyScale(cellColor);
|
float gray = GreyScale(cellColor);
|
||||||
|
|
||||||
int n = 4096;
|
int n = 4096;
|
||||||
|
|
||||||
// Character set from https://www.shadertoy.com/view/lssGDj
|
// Character set from https://www.shadertoy.com/view/lssGDj
|
||||||
// Create new bitmaps https://thrill-project.com/archiv/coding/bitmap/
|
// Create new bitmaps https://thrill-project.com/archiv/coding/bitmap/
|
||||||
if (gray > 0.2) n = 65600; // :
|
if (gray > 0.2) n = 65600; // :
|
||||||
if (gray > 0.3) n = 18725316; // v
|
if (gray > 0.3) n = 18725316; // v
|
||||||
if (gray > 0.4) n = 15255086; // o
|
if (gray > 0.4) n = 15255086; // o
|
||||||
if (gray > 0.5) n = 13121101; // &
|
if (gray > 0.5) n = 13121101; // &
|
||||||
if (gray > 0.6) n = 15252014; // 8
|
if (gray > 0.6) n = 15252014; // 8
|
||||||
if (gray > 0.7) n = 13195790; // @
|
if (gray > 0.7) n = 13195790; // @
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ void main()
|
||||||
|
|
||||||
// NOTE: Implement here your fragment shader code
|
// NOTE: Implement here your fragment shader code
|
||||||
|
|
||||||
// final color is the color from the texture
|
// final color is the color from the texture
|
||||||
// times the tint color (colDiffuse)
|
// times the tint color (colDiffuse)
|
||||||
// times the fragment color (interpolated vertex color)
|
// times the fragment color (interpolated vertex color)
|
||||||
finalColor = texelColor*colDiffuse*fragColor;
|
finalColor = texelColor*colDiffuse*fragColor;
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ out vec4 finalColor;
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec4 texelColor = texture(texture0, fragTexCoord);
|
vec4 texelColor = texture(texture0, fragTexCoord);
|
||||||
|
|
||||||
finalColor = texelColor*colDiffuse*fragColor;
|
finalColor = texelColor*colDiffuse*fragColor;
|
||||||
gl_FragDepth = 1.0 - finalColor.z;
|
gl_FragDepth = 1.0 - finalColor.z;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ uniform mat4 matProjection;
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec4 worldPos = matModel*vec4(vertexPosition, 1.0);
|
vec4 worldPos = matModel*vec4(vertexPosition, 1.0);
|
||||||
fragPosition = worldPos.xyz;
|
fragPosition = worldPos.xyz;
|
||||||
fragTexCoord = vertexTexCoord;
|
fragTexCoord = vertexTexCoord;
|
||||||
|
|
||||||
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
|
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ out vec4 finalColor;
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec4 texelColor = texture(texture0, fragTexCoord);
|
vec4 texelColor = texture(texture0, fragTexCoord);
|
||||||
|
|
||||||
finalColor = texelColor*colDiffuse*fragColor;
|
finalColor = texelColor*colDiffuse*fragColor;
|
||||||
gl_FragDepth = finalColor.z;
|
gl_FragDepth = finalColor.z;
|
||||||
}
|
}
|
||||||
|
|
@ -33,7 +33,7 @@ float sdHorseshoe(in vec3 p, in vec2 c, in float r, in float le, vec2 w)
|
||||||
p.xy = mat2(-c.x, c.y, c.y, c.x)*p.xy;
|
p.xy = mat2(-c.x, c.y, c.y, c.x)*p.xy;
|
||||||
p.xy = vec2(((p.y > 0.0) || (p.x > 0.0))? p.x : l*sign(-c.x), (p.x>0.0)? p.y : l);
|
p.xy = vec2(((p.y > 0.0) || (p.x > 0.0))? p.x : l*sign(-c.x), (p.x>0.0)? p.y : l);
|
||||||
p.xy = vec2(p.x, abs(p.y - r)) - vec2(le, 0.0);
|
p.xy = vec2(p.x, abs(p.y - r)) - vec2(le, 0.0);
|
||||||
|
|
||||||
vec2 q = vec2(length(max(p.xy, 0.0)) + min(0.0, max(p.x, p.y)), p.z);
|
vec2 q = vec2(length(max(p.xy, 0.0)) + min(0.0, max(p.x, p.y)), p.z);
|
||||||
vec2 d = abs(q) - w;
|
vec2 d = abs(q) - w;
|
||||||
return min(max(d.x, d.y), 0.0) + length(max(d, 0.0));
|
return min(max(d.x, d.y), 0.0) + length(max(d, 0.0));
|
||||||
|
|
@ -54,7 +54,7 @@ float sdSixWayCutHollowSphere(vec3 p, float r, float h, float t)
|
||||||
|
|
||||||
vec2 q = vec2(length(ap.yz), ap.x);
|
vec2 q = vec2(length(ap.yz), ap.x);
|
||||||
float w = sqrt(r*r-h*h);
|
float w = sqrt(r*r-h*h);
|
||||||
|
|
||||||
return ((h*q.x < w*q.y)? length(q - vec2(w, h)) : abs(length(q) - r)) - t;
|
return ((h*q.x < w*q.y)? length(q - vec2(w, h)) : abs(length(q) - r)) - t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -79,7 +79,7 @@ vec2 map(in vec3 pos)
|
||||||
{
|
{
|
||||||
vec2 res = vec2(sdHorseshoe(pos - vec3(-1.0, 0.08, 1.0), vec2(cos(1.3), sin(1.3)), 0.2, 0.3, vec2(0.03,0.5)), 11.5);
|
vec2 res = vec2(sdHorseshoe(pos - vec3(-1.0, 0.08, 1.0), vec2(cos(1.3), sin(1.3)), 0.2, 0.3, vec2(0.03,0.5)), 11.5);
|
||||||
res = opU(res, vec2(sdSixWayCutHollowSphere(pos-vec3(0.0, 1.0, 0.0), 4.0, 3.5, 0.5), 4.5));
|
res = opU(res, vec2(sdSixWayCutHollowSphere(pos-vec3(0.0, 1.0, 0.0), 4.0, 3.5, 0.5), 4.5));
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -105,8 +105,8 @@ vec2 raycast(in vec3 ro, in vec3 rd)
|
||||||
if (t > tmax) break;
|
if (t > tmax) break;
|
||||||
vec2 h = map(ro + rd*t);
|
vec2 h = map(ro + rd*t);
|
||||||
if (abs(h.x )< (0.0001*t))
|
if (abs(h.x )< (0.0001*t))
|
||||||
{
|
{
|
||||||
res = vec2(t, h.y);
|
res = vec2(t, h.y);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
t += h.x;
|
t += h.x;
|
||||||
|
|
@ -131,9 +131,9 @@ float calcSoftshadow(in vec3 ro, in vec3 rd, in float mint, in float tmax)
|
||||||
t += clamp(h, 0.01, 0.2);
|
t += clamp(h, 0.01, 0.2);
|
||||||
if ((res < 0.004) || (t > tmax)) break;
|
if ((res < 0.004) || (t > tmax)) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = clamp(res, 0.0, 1.0);
|
res = clamp(res, 0.0, 1.0);
|
||||||
|
|
||||||
return res*res*(3.0-2.0*res);
|
return res*res*(3.0-2.0*res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,9 +141,9 @@ float calcSoftshadow(in vec3 ro, in vec3 rd, in float mint, in float tmax)
|
||||||
vec3 calcNormal(in vec3 pos)
|
vec3 calcNormal(in vec3 pos)
|
||||||
{
|
{
|
||||||
vec2 e = vec2(1.0, -1.0)*0.5773*0.0005;
|
vec2 e = vec2(1.0, -1.0)*0.5773*0.0005;
|
||||||
return normalize(e.xyy*map(pos + e.xyy).x +
|
return normalize(e.xyy*map(pos + e.xyy).x +
|
||||||
e.yyx*map(pos + e.yyx).x +
|
e.yyx*map(pos + e.yyx).x +
|
||||||
e.yxy*map(pos + e.yxy).x +
|
e.yxy*map(pos + e.yxy).x +
|
||||||
e.xxx*map(pos + e.xxx).x);
|
e.xxx*map(pos + e.xxx).x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -160,7 +160,7 @@ float calcAO(in vec3 pos, in vec3 nor)
|
||||||
sca *= 0.95;
|
sca *= 0.95;
|
||||||
if (occ>0.35) break;
|
if (occ>0.35) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return clamp(1.0 - 3.0*occ, 0.0, 1.0)*(0.5+0.5*nor.y);
|
return clamp(1.0 - 3.0*occ, 0.0, 1.0)*(0.5+0.5*nor.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -172,15 +172,15 @@ float checkersGradBox(in vec2 p)
|
||||||
// analytical integral (box filter)
|
// analytical integral (box filter)
|
||||||
vec2 i = 2.0*(abs(fract((p - 0.5*w)*0.5)-0.5) - abs(fract((p + 0.5*w)*0.5) - 0.5))/w;
|
vec2 i = 2.0*(abs(fract((p - 0.5*w)*0.5)-0.5) - abs(fract((p + 0.5*w)*0.5) - 0.5))/w;
|
||||||
// xor pattern
|
// xor pattern
|
||||||
return (0.5 - 0.5*i.x*i.y);
|
return (0.5 - 0.5*i.x*i.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.shadertoy.com/view/tdS3DG
|
// https://www.shadertoy.com/view/tdS3DG
|
||||||
vec4 render(in vec3 ro, in vec3 rd)
|
vec4 render(in vec3 ro, in vec3 rd)
|
||||||
{
|
{
|
||||||
// background
|
// background
|
||||||
vec3 col = vec3(0.7, 0.7, 0.9) - max(rd.y,0.0)*0.3;
|
vec3 col = vec3(0.7, 0.7, 0.9) - max(rd.y,0.0)*0.3;
|
||||||
|
|
||||||
// raycast scene
|
// raycast scene
|
||||||
vec2 res = raycast(ro,rd);
|
vec2 res = raycast(ro,rd);
|
||||||
float t = res.x;
|
float t = res.x;
|
||||||
|
|
@ -190,11 +190,11 @@ vec4 render(in vec3 ro, in vec3 rd)
|
||||||
vec3 pos = ro + t*rd;
|
vec3 pos = ro + t*rd;
|
||||||
vec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal(pos);
|
vec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal(pos);
|
||||||
vec3 ref = reflect(rd, nor);
|
vec3 ref = reflect(rd, nor);
|
||||||
|
|
||||||
// material
|
// material
|
||||||
col = 0.2 + 0.2*sin(m*2.0 + vec3(0.0,1.0,2.0));
|
col = 0.2 + 0.2*sin(m*2.0 + vec3(0.0,1.0,2.0));
|
||||||
float ks = 1.0;
|
float ks = 1.0;
|
||||||
|
|
||||||
if (m < 1.5)
|
if (m < 1.5)
|
||||||
{
|
{
|
||||||
float f = checkersGradBox(3.0*pos.xz);
|
float f = checkersGradBox(3.0*pos.xz);
|
||||||
|
|
@ -204,7 +204,7 @@ vec4 render(in vec3 ro, in vec3 rd)
|
||||||
|
|
||||||
// lighting
|
// lighting
|
||||||
float occ = calcAO(pos, nor);
|
float occ = calcAO(pos, nor);
|
||||||
|
|
||||||
vec3 lin = vec3(0.0);
|
vec3 lin = vec3(0.0);
|
||||||
|
|
||||||
// sun
|
// sun
|
||||||
|
|
@ -245,7 +245,7 @@ vec4 render(in vec3 ro, in vec3 rd)
|
||||||
dif *= occ;
|
dif *= occ;
|
||||||
lin += col*0.25*dif*vec3(1.00,1.00,1.00);
|
lin += col*0.25*dif*vec3(1.00,1.00,1.00);
|
||||||
}
|
}
|
||||||
|
|
||||||
col = lin;
|
col = lin;
|
||||||
|
|
||||||
col = mix(col, vec3(0.7,0.7,0.9), 1.0-exp(-0.0001*t*t*t));
|
col = mix(col, vec3(0.7,0.7,0.9), 1.0-exp(-0.0001*t*t*t));
|
||||||
|
|
@ -285,7 +285,7 @@ void main()
|
||||||
color = res.xyz;
|
color = res.xyz;
|
||||||
depth = CalcDepth(rd,res.w);
|
depth = CalcDepth(rd,res.w);
|
||||||
}
|
}
|
||||||
|
|
||||||
finalColor = vec4(color , 1.0);
|
finalColor = vec4(color , 1.0);
|
||||||
gl_FragDepth = depth;
|
gl_FragDepth = depth;
|
||||||
}
|
}
|
||||||
|
|
@ -54,7 +54,7 @@ void main()
|
||||||
|
|
||||||
float specCo = 0.0;
|
float specCo = 0.0;
|
||||||
|
|
||||||
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent); // 16 refers to shine
|
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent);
|
||||||
|
|
||||||
specular += specCo;
|
specular += specCo;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ void main()
|
||||||
// to the palette index by scaling up from [0..1] to [0..255]
|
// to the palette index by scaling up from [0..1] to [0..255]
|
||||||
int index = int(texelColor.r*255.0);
|
int index = int(texelColor.r*255.0);
|
||||||
ivec3 color = palette[index];
|
ivec3 color = palette[index];
|
||||||
|
|
||||||
//finalColor = texture(palette, texelColor.xy); // Alternative to ivec3
|
//finalColor = texture(palette, texelColor.xy); // Alternative to ivec3
|
||||||
|
|
||||||
// Calculate final fragment color. Note that the palette color components
|
// Calculate final fragment color. Note that the palette color components
|
||||||
|
|
|
||||||
|
|
@ -84,11 +84,11 @@ vec3 ComputePBR()
|
||||||
{
|
{
|
||||||
vec3 albedo = texture(albedoMap,vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb;
|
vec3 albedo = texture(albedoMap,vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb;
|
||||||
albedo = vec3(albedoColor.x*albedo.x, albedoColor.y*albedo.y, albedoColor.z*albedo.z);
|
albedo = vec3(albedoColor.x*albedo.x, albedoColor.y*albedo.y, albedoColor.z*albedo.z);
|
||||||
|
|
||||||
float metallic = clamp(metallicValue, 0.0, 1.0);
|
float metallic = clamp(metallicValue, 0.0, 1.0);
|
||||||
float roughness = clamp(roughnessValue, 0.0, 1.0);
|
float roughness = clamp(roughnessValue, 0.0, 1.0);
|
||||||
float ao = clamp(aoValue, 0.0, 1.0);
|
float ao = clamp(aoValue, 0.0, 1.0);
|
||||||
|
|
||||||
if (useTexMRA == 1)
|
if (useTexMRA == 1)
|
||||||
{
|
{
|
||||||
vec4 mra = texture(mraMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y));
|
vec4 mra = texture(mraMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y));
|
||||||
|
|
@ -133,18 +133,18 @@ vec3 ComputePBR()
|
||||||
vec3 F = SchlickFresnel(hDotV, baseRefl); // Fresnel proportion of specular reflectance
|
vec3 F = SchlickFresnel(hDotV, baseRefl); // Fresnel proportion of specular reflectance
|
||||||
|
|
||||||
vec3 spec = (D*G*F)/(4.0*nDotV*nDotL);
|
vec3 spec = (D*G*F)/(4.0*nDotV*nDotL);
|
||||||
|
|
||||||
// Difuse and spec light can't be above 1.0
|
// Difuse and spec light can't be above 1.0
|
||||||
// kD = 1.0 - kS diffuse component is equal 1.0 - spec comonent
|
// kD = 1.0 - kS diffuse component is equal 1.0 - spec comonent
|
||||||
vec3 kD = vec3(1.0) - F;
|
vec3 kD = vec3(1.0) - F;
|
||||||
|
|
||||||
// Mult kD by the inverse of metallnes, only non-metals should have diffuse light
|
// Mult kD by the inverse of metallnes, only non-metals should have diffuse light
|
||||||
kD *= 1.0 - metallic;
|
kD *= 1.0 - metallic;
|
||||||
lightAccum += ((kD*albedo.rgb/PI + spec)*radiance*nDotL)*lights[i].enabled; // Angle of light has impact on result
|
lightAccum += ((kD*albedo.rgb/PI + spec)*radiance*nDotL)*lights[i].enabled; // Angle of light has impact on result
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 ambientFinal = (ambientColor + albedo)*ambient*0.5;
|
vec3 ambientFinal = (ambientColor + albedo)*ambient*0.5;
|
||||||
|
|
||||||
return (ambientFinal + lightAccum*ao + emissive);
|
return (ambientFinal + lightAccum*ao + emissive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -154,7 +154,7 @@ void main()
|
||||||
|
|
||||||
// HDR tonemapping
|
// HDR tonemapping
|
||||||
color = pow(color, color + vec3(1.0));
|
color = pow(color, color + vec3(1.0));
|
||||||
|
|
||||||
// Gamma correction
|
// Gamma correction
|
||||||
color = pow(color, vec3(1.0/2.2));
|
color = pow(color, vec3(1.0/2.2));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ uniform mat4 mvp;
|
||||||
uniform mat4 matModel;
|
uniform mat4 matModel;
|
||||||
uniform mat4 matNormal;
|
uniform mat4 matNormal;
|
||||||
|
|
||||||
uniform float time;
|
uniform float time;
|
||||||
|
|
||||||
uniform sampler2D perlinNoiseMap;
|
uniform sampler2D perlinNoiseMap;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ int main(void)
|
||||||
// Set the texture tiling using a shader
|
// Set the texture tiling using a shader
|
||||||
float tiling[2] = { 3.0f, 3.0f };
|
float tiling[2] = { 3.0f, 3.0f };
|
||||||
Shader shader = LoadShader(0, TextFormat("resources/shaders/glsl%i/tiling.fs", GLSL_VERSION));
|
Shader shader = LoadShader(0, TextFormat("resources/shaders/glsl%i/tiling.fs", GLSL_VERSION));
|
||||||
|
SetTextureWrap(texture, TEXTURE_WRAP_REPEAT);
|
||||||
SetShaderValue(shader, GetShaderLocation(shader, "tiling"), tiling, SHADER_UNIFORM_VEC2);
|
SetShaderValue(shader, GetShaderLocation(shader, "tiling"), tiling, SHADER_UNIFORM_VEC2);
|
||||||
model.materials[0].shader = shader;
|
model.materials[0].shader = shader;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,12 +38,12 @@ int main(void)
|
||||||
|
|
||||||
// Define characters to draw
|
// Define characters to draw
|
||||||
// NOTE: raylib supports UTF-8 encoding, following list is actually codified as UTF8 internally
|
// NOTE: raylib supports UTF-8 encoding, following list is actually codified as UTF8 internally
|
||||||
const char msg[256] = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHI\nJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmn\nopqrstuvwxyz{|}~¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓ\nÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷\nøùúûüýþÿ";
|
const char msg[256] = "!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHI\nJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmn\nopqrstuvwxyz{|}~¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓ\nÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷\nøùúûüýþÿ";
|
||||||
|
|
||||||
// NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required)
|
// NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required)
|
||||||
|
|
||||||
// BMFont (AngelCode) : Font data and image atlas have been generated using external program
|
// BMFont (AngelCode) : Font data and image atlas have been generated using external program
|
||||||
Font fontBm = LoadFont("resources/pixantiqua.fnt");
|
Font fontBm = LoadFont("resources/pixantiqua.fnt"); // Requires "resources/pixantiqua.png"
|
||||||
|
|
||||||
// TTF font : Font data and atlas are generated directly from TTF
|
// TTF font : Font data and atlas are generated directly from TTF
|
||||||
// NOTE: We define a font base size of 32 pixels tall and up-to 250 characters
|
// NOTE: We define a font base size of 32 pixels tall and up-to 250 characters
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ int main()
|
||||||
DrawFPS(10, 10);
|
DrawFPS(10, 10);
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseWindow();
|
CloseWindow();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ int main()
|
||||||
int screenHeight = 450;
|
int screenHeight = 450;
|
||||||
|
|
||||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window");
|
InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window");
|
||||||
|
|
||||||
SetTargetFPS(60);
|
SetTargetFPS(60);
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -44,7 +44,7 @@ int main()
|
||||||
}
|
}
|
||||||
|
|
||||||
// De-Initialization
|
// De-Initialization
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
CloseWindow(); // Close window and OpenGL context
|
CloseWindow(); // Close window and OpenGL context
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2960,24 +2960,6 @@
|
||||||
<Param name="Color tint" />
|
<Param name="Color tint" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="DrawModelPoints" func="yes">
|
|
||||||
<Overload retVal="void" descr="Draw a model as points">
|
|
||||||
<Param name="Model model" />
|
|
||||||
<Param name="Vector3 position" />
|
|
||||||
<Param name="float scale" />
|
|
||||||
<Param name="Color tint" />
|
|
||||||
</Overload>
|
|
||||||
</KeyWord>
|
|
||||||
<KeyWord name="DrawModelPointsEx" func="yes">
|
|
||||||
<Overload retVal="void" descr="Draw a model as points with extended parameters">
|
|
||||||
<Param name="Model model" />
|
|
||||||
<Param name="Vector3 position" />
|
|
||||||
<Param name="Vector3 rotationAxis" />
|
|
||||||
<Param name="float rotationAngle" />
|
|
||||||
<Param name="Vector3 scale" />
|
|
||||||
<Param name="Color tint" />
|
|
||||||
</Overload>
|
|
||||||
</KeyWord>
|
|
||||||
<KeyWord name="DrawBoundingBox" func="yes">
|
<KeyWord name="DrawBoundingBox" func="yes">
|
||||||
<Overload retVal="void" descr="Draw bounding box (wires)">
|
<Overload retVal="void" descr="Draw bounding box (wires)">
|
||||||
<Param name="BoundingBox box" />
|
<Param name="BoundingBox box" />
|
||||||
|
|
@ -3013,7 +2995,7 @@
|
||||||
<Param name="Vector2 size" />
|
<Param name="Vector2 size" />
|
||||||
<Param name="Vector2 origin" />
|
<Param name="Vector2 origin" />
|
||||||
<Param name="float rotation" />
|
<Param name="float rotation" />
|
||||||
<Param name="°ñ_)% " />
|
<Param name="<EFBFBD><EFBFBD>_)% " />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,9 @@
|
||||||
<Param name="float alpha" />
|
<Param name="float alpha" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
|
|
||||||
NOTE: Generated XML text should be copied inside raylib\Notepad++\plugins\APIs\c.xml
|
NOTE: Generated XML text should be copied inside raylib\Notepad++\plugins\APIs\c.xml
|
||||||
|
|
||||||
WARNING: Be careful with functions that split parameters into several lines, it breaks the process!
|
WARNING: Be careful with functions that split parameters into several lines, it breaks the process!
|
||||||
|
|
||||||
LICENSE: zlib/libpng
|
LICENSE: zlib/libpng
|
||||||
|
|
@ -42,13 +42,13 @@ int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
FILE *rFile = fopen(argv[1], "rt");
|
FILE *rFile = fopen(argv[1], "rt");
|
||||||
FILE *rxmlFile = fopen("raylib_npp.xml", "wt");
|
FILE *rxmlFile = fopen("raylib_npp.xml", "wt");
|
||||||
|
|
||||||
if ((rFile == NULL) || (rxmlFile == NULL))
|
if ((rFile == NULL) || (rxmlFile == NULL))
|
||||||
{
|
{
|
||||||
printf("File could not be opened.\n");
|
printf("File could not be opened.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *buffer = (char *)calloc(MAX_BUFFER_SIZE, 1);
|
char *buffer = (char *)calloc(MAX_BUFFER_SIZE, 1);
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
|
|
@ -56,7 +56,7 @@ int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
// Read one full line
|
// Read one full line
|
||||||
fgets(buffer, MAX_BUFFER_SIZE, rFile);
|
fgets(buffer, MAX_BUFFER_SIZE, rFile);
|
||||||
|
|
||||||
if (buffer[0] == '/') fprintf(rxmlFile, " <!--%.*s -->\n", strlen(buffer) - 3, buffer + 2);
|
if (buffer[0] == '/') fprintf(rxmlFile, " <!--%.*s -->\n", strlen(buffer) - 3, buffer + 2);
|
||||||
else if (buffer[0] == '\n') fprintf(rxmlFile, "%s", buffer); // Direct copy of code comments
|
else if (buffer[0] == '\n') fprintf(rxmlFile, "%s", buffer); // Direct copy of code comments
|
||||||
else if (strncmp(buffer, "RLAPI", 5) == 0) // raylib function declaration
|
else if (strncmp(buffer, "RLAPI", 5) == 0) // raylib function declaration
|
||||||
|
|
@ -65,33 +65,33 @@ int main(int argc, char *argv[])
|
||||||
char funcTypeAux[64];
|
char funcTypeAux[64];
|
||||||
char funcName[64];
|
char funcName[64];
|
||||||
char funcDesc[256];
|
char funcDesc[256];
|
||||||
|
|
||||||
char params[128];
|
char params[128];
|
||||||
char paramType[16][16];
|
char paramType[16][16];
|
||||||
char paramName[16][32];
|
char paramName[16][32];
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
char *ptr = NULL;
|
char *ptr = NULL;
|
||||||
|
|
||||||
sscanf(buffer, "RLAPI %s %[^(]s", funcType, funcName);
|
sscanf(buffer, "RLAPI %s %[^(]s", funcType, funcName);
|
||||||
|
|
||||||
if (strcmp(funcType, "const") == 0)
|
if (strcmp(funcType, "const") == 0)
|
||||||
{
|
{
|
||||||
sscanf(buffer, "RLAPI %s %s %[^(]s", funcType, funcTypeAux, funcName);
|
sscanf(buffer, "RLAPI %s %s %[^(]s", funcType, funcTypeAux, funcName);
|
||||||
strcat(funcType, " ");
|
strcat(funcType, " ");
|
||||||
strcat(funcType, funcTypeAux);
|
strcat(funcType, funcTypeAux);
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr = strchr(buffer, '/');
|
ptr = strchr(buffer, '/');
|
||||||
index = (int)(ptr - buffer);
|
index = (int)(ptr - buffer);
|
||||||
|
|
||||||
sscanf(buffer + index, "%[^\n]s", funcDesc); // Read function comment after declaration
|
sscanf(buffer + index, "%[^\n]s", funcDesc); // Read function comment after declaration
|
||||||
|
|
||||||
ptr = strchr(buffer, '(');
|
ptr = strchr(buffer, '(');
|
||||||
|
|
||||||
if (ptr != NULL) index = (int)(ptr - buffer);
|
if (ptr != NULL) index = (int)(ptr - buffer);
|
||||||
else printf("Character not found!\n");
|
else printf("Character not found!\n");
|
||||||
|
|
||||||
sscanf(buffer + (index + 1), "%[^)]s", params); // Read what's inside '(' and ')'
|
sscanf(buffer + (index + 1), "%[^)]s", params); // Read what's inside '(' and ')'
|
||||||
|
|
||||||
// Scan params string for number of func params, type and name
|
// Scan params string for number of func params, type and name
|
||||||
|
|
@ -102,23 +102,23 @@ int main(int argc, char *argv[])
|
||||||
if ((funcName[0] == '*') && (funcName[1] == '*')) fprintf(rxmlFile, " <KeyWord name=\"%s\" func=\"yes\">\n", funcName + 2);
|
if ((funcName[0] == '*') && (funcName[1] == '*')) fprintf(rxmlFile, " <KeyWord name=\"%s\" func=\"yes\">\n", funcName + 2);
|
||||||
else if (funcName[0] == '*') fprintf(rxmlFile, " <KeyWord name=\"%s\" func=\"yes\">\n", funcName + 1);
|
else if (funcName[0] == '*') fprintf(rxmlFile, " <KeyWord name=\"%s\" func=\"yes\">\n", funcName + 1);
|
||||||
else fprintf(rxmlFile, " <KeyWord name=\"%s\" func=\"yes\">\n", funcName);
|
else fprintf(rxmlFile, " <KeyWord name=\"%s\" func=\"yes\">\n", funcName);
|
||||||
|
|
||||||
fprintf(rxmlFile, " <Overload retVal=\"%s\" descr=\"%s\">", funcType, funcDesc + 3);
|
fprintf(rxmlFile, " <Overload retVal=\"%s\" descr=\"%s\">", funcType, funcDesc + 3);
|
||||||
|
|
||||||
bool paramsVoid = false;
|
bool paramsVoid = false;
|
||||||
|
|
||||||
char paramConst[8][16];
|
char paramConst[8][16];
|
||||||
|
|
||||||
while (paramPtr[paramsCount] != NULL)
|
while (paramPtr[paramsCount] != NULL)
|
||||||
{
|
{
|
||||||
sscanf(paramPtr[paramsCount], "%s %s\n", paramType[paramsCount], paramName[paramsCount]);
|
sscanf(paramPtr[paramsCount], "%s %s\n", paramType[paramsCount], paramName[paramsCount]);
|
||||||
|
|
||||||
if (strcmp(paramType[paramsCount], "void") == 0)
|
if (strcmp(paramType[paramsCount], "void") == 0)
|
||||||
{
|
{
|
||||||
paramsVoid = true;
|
paramsVoid = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((strcmp(paramType[paramsCount], "const") == 0) || (strcmp(paramType[paramsCount], "unsigned") == 0))
|
if ((strcmp(paramType[paramsCount], "const") == 0) || (strcmp(paramType[paramsCount], "unsigned") == 0))
|
||||||
{
|
{
|
||||||
sscanf(paramPtr[paramsCount], "%s %s %s\n", paramConst[paramsCount], paramType[paramsCount], paramName[paramsCount]);
|
sscanf(paramPtr[paramsCount], "%s %s %s\n", paramConst[paramsCount], paramType[paramsCount], paramName[paramsCount]);
|
||||||
|
|
@ -130,17 +130,17 @@ int main(int argc, char *argv[])
|
||||||
paramsCount++;
|
paramsCount++;
|
||||||
paramPtr[paramsCount] = strtok(NULL, ",");
|
paramPtr[paramsCount] = strtok(NULL, ",");
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(rxmlFile, "%s</Overload>\n", paramsVoid ? "" : "\n ");
|
fprintf(rxmlFile, "%s</Overload>\n", paramsVoid ? "" : "\n ");
|
||||||
fprintf(rxmlFile, " </KeyWord>\n");
|
fprintf(rxmlFile, " </KeyWord>\n");
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
printf("Function processed %02i: %s\n", count, funcName);
|
printf("Function processed %02i: %s\n", count, funcName);
|
||||||
|
|
||||||
memset(buffer, 0, MAX_BUFFER_SIZE);
|
memset(buffer, 0, MAX_BUFFER_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
fclose(rFile);
|
fclose(rFile);
|
||||||
fclose(rxmlFile);
|
fclose(rxmlFile);
|
||||||
|
|
|
||||||
|
|
@ -600,8 +600,6 @@ RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint);
|
||||||
RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters
|
RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters
|
||||||
RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set)
|
RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set)
|
||||||
RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters
|
RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters
|
||||||
RLAPI void DrawModelPoints(Model model, Vector3 position, float scale, Color tint); // Draw a model as points
|
|
||||||
RLAPI void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model as points with extended parameters
|
|
||||||
RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires)
|
RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires)
|
||||||
RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture
|
RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture
|
||||||
RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source
|
RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source
|
||||||
|
|
|
||||||
211
src/external/cgltf.h
vendored
211
src/external/cgltf.h
vendored
|
|
@ -1,7 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* cgltf - a single-file glTF 2.0 parser written in C99.
|
* cgltf - a single-file glTF 2.0 parser written in C99.
|
||||||
*
|
*
|
||||||
* Version: 1.14
|
* Version: 1.15
|
||||||
*
|
*
|
||||||
* Website: https://github.com/jkuhlmann/cgltf
|
* Website: https://github.com/jkuhlmann/cgltf
|
||||||
*
|
*
|
||||||
|
|
@ -141,7 +141,7 @@ typedef struct cgltf_memory_options
|
||||||
typedef struct cgltf_file_options
|
typedef struct cgltf_file_options
|
||||||
{
|
{
|
||||||
cgltf_result(*read)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, const char* path, cgltf_size* size, void** data);
|
cgltf_result(*read)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, const char* path, cgltf_size* size, void** data);
|
||||||
void (*release)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data);
|
void (*release)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data, cgltf_size size);
|
||||||
void* user_data;
|
void* user_data;
|
||||||
} cgltf_file_options;
|
} cgltf_file_options;
|
||||||
|
|
||||||
|
|
@ -296,6 +296,7 @@ typedef enum cgltf_meshopt_compression_filter {
|
||||||
cgltf_meshopt_compression_filter_octahedral,
|
cgltf_meshopt_compression_filter_octahedral,
|
||||||
cgltf_meshopt_compression_filter_quaternion,
|
cgltf_meshopt_compression_filter_quaternion,
|
||||||
cgltf_meshopt_compression_filter_exponential,
|
cgltf_meshopt_compression_filter_exponential,
|
||||||
|
cgltf_meshopt_compression_filter_color,
|
||||||
cgltf_meshopt_compression_filter_max_enum
|
cgltf_meshopt_compression_filter_max_enum
|
||||||
} cgltf_meshopt_compression_filter;
|
} cgltf_meshopt_compression_filter;
|
||||||
|
|
||||||
|
|
@ -308,6 +309,7 @@ typedef struct cgltf_meshopt_compression
|
||||||
cgltf_size count;
|
cgltf_size count;
|
||||||
cgltf_meshopt_compression_mode mode;
|
cgltf_meshopt_compression_mode mode;
|
||||||
cgltf_meshopt_compression_filter filter;
|
cgltf_meshopt_compression_filter filter;
|
||||||
|
cgltf_bool is_khr;
|
||||||
} cgltf_meshopt_compression;
|
} cgltf_meshopt_compression;
|
||||||
|
|
||||||
typedef struct cgltf_buffer_view
|
typedef struct cgltf_buffer_view
|
||||||
|
|
@ -376,13 +378,29 @@ typedef struct cgltf_image
|
||||||
cgltf_extension* extensions;
|
cgltf_extension* extensions;
|
||||||
} cgltf_image;
|
} cgltf_image;
|
||||||
|
|
||||||
|
typedef enum cgltf_filter_type {
|
||||||
|
cgltf_filter_type_undefined = 0,
|
||||||
|
cgltf_filter_type_nearest = 9728,
|
||||||
|
cgltf_filter_type_linear = 9729,
|
||||||
|
cgltf_filter_type_nearest_mipmap_nearest = 9984,
|
||||||
|
cgltf_filter_type_linear_mipmap_nearest = 9985,
|
||||||
|
cgltf_filter_type_nearest_mipmap_linear = 9986,
|
||||||
|
cgltf_filter_type_linear_mipmap_linear = 9987
|
||||||
|
} cgltf_filter_type;
|
||||||
|
|
||||||
|
typedef enum cgltf_wrap_mode {
|
||||||
|
cgltf_wrap_mode_clamp_to_edge = 33071,
|
||||||
|
cgltf_wrap_mode_mirrored_repeat = 33648,
|
||||||
|
cgltf_wrap_mode_repeat = 10497
|
||||||
|
} cgltf_wrap_mode;
|
||||||
|
|
||||||
typedef struct cgltf_sampler
|
typedef struct cgltf_sampler
|
||||||
{
|
{
|
||||||
char* name;
|
char* name;
|
||||||
cgltf_int mag_filter;
|
cgltf_filter_type mag_filter;
|
||||||
cgltf_int min_filter;
|
cgltf_filter_type min_filter;
|
||||||
cgltf_int wrap_s;
|
cgltf_wrap_mode wrap_s;
|
||||||
cgltf_int wrap_t;
|
cgltf_wrap_mode wrap_t;
|
||||||
cgltf_extras extras;
|
cgltf_extras extras;
|
||||||
cgltf_size extensions_count;
|
cgltf_size extensions_count;
|
||||||
cgltf_extension* extensions;
|
cgltf_extension* extensions;
|
||||||
|
|
@ -500,6 +518,14 @@ typedef struct cgltf_iridescence
|
||||||
cgltf_texture_view iridescence_thickness_texture;
|
cgltf_texture_view iridescence_thickness_texture;
|
||||||
} cgltf_iridescence;
|
} cgltf_iridescence;
|
||||||
|
|
||||||
|
typedef struct cgltf_diffuse_transmission
|
||||||
|
{
|
||||||
|
cgltf_texture_view diffuse_transmission_texture;
|
||||||
|
cgltf_float diffuse_transmission_factor;
|
||||||
|
cgltf_float diffuse_transmission_color_factor[3];
|
||||||
|
cgltf_texture_view diffuse_transmission_color_texture;
|
||||||
|
} cgltf_diffuse_transmission;
|
||||||
|
|
||||||
typedef struct cgltf_anisotropy
|
typedef struct cgltf_anisotropy
|
||||||
{
|
{
|
||||||
cgltf_float anisotropy_strength;
|
cgltf_float anisotropy_strength;
|
||||||
|
|
@ -525,6 +551,7 @@ typedef struct cgltf_material
|
||||||
cgltf_bool has_sheen;
|
cgltf_bool has_sheen;
|
||||||
cgltf_bool has_emissive_strength;
|
cgltf_bool has_emissive_strength;
|
||||||
cgltf_bool has_iridescence;
|
cgltf_bool has_iridescence;
|
||||||
|
cgltf_bool has_diffuse_transmission;
|
||||||
cgltf_bool has_anisotropy;
|
cgltf_bool has_anisotropy;
|
||||||
cgltf_bool has_dispersion;
|
cgltf_bool has_dispersion;
|
||||||
cgltf_pbr_metallic_roughness pbr_metallic_roughness;
|
cgltf_pbr_metallic_roughness pbr_metallic_roughness;
|
||||||
|
|
@ -537,6 +564,7 @@ typedef struct cgltf_material
|
||||||
cgltf_volume volume;
|
cgltf_volume volume;
|
||||||
cgltf_emissive_strength emissive_strength;
|
cgltf_emissive_strength emissive_strength;
|
||||||
cgltf_iridescence iridescence;
|
cgltf_iridescence iridescence;
|
||||||
|
cgltf_diffuse_transmission diffuse_transmission;
|
||||||
cgltf_anisotropy anisotropy;
|
cgltf_anisotropy anisotropy;
|
||||||
cgltf_dispersion dispersion;
|
cgltf_dispersion dispersion;
|
||||||
cgltf_texture_view normal_texture;
|
cgltf_texture_view normal_texture;
|
||||||
|
|
@ -743,6 +771,7 @@ typedef struct cgltf_data
|
||||||
{
|
{
|
||||||
cgltf_file_type file_type;
|
cgltf_file_type file_type;
|
||||||
void* file_data;
|
void* file_data;
|
||||||
|
cgltf_size file_size;
|
||||||
|
|
||||||
cgltf_asset asset;
|
cgltf_asset asset;
|
||||||
|
|
||||||
|
|
@ -844,6 +873,8 @@ void cgltf_node_transform_world(const cgltf_node* node, cgltf_float* out_matrix)
|
||||||
|
|
||||||
const uint8_t* cgltf_buffer_view_data(const cgltf_buffer_view* view);
|
const uint8_t* cgltf_buffer_view_data(const cgltf_buffer_view* view);
|
||||||
|
|
||||||
|
const cgltf_accessor* cgltf_find_accessor(const cgltf_primitive* prim, cgltf_attribute_type type, cgltf_int index);
|
||||||
|
|
||||||
cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size);
|
cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size);
|
||||||
cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size);
|
cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size);
|
||||||
cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index);
|
cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index);
|
||||||
|
|
@ -1071,9 +1102,10 @@ static cgltf_result cgltf_default_file_read(const struct cgltf_memory_options* m
|
||||||
return cgltf_result_success;
|
return cgltf_result_success;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cgltf_default_file_release(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data)
|
static void cgltf_default_file_release(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data, cgltf_size size)
|
||||||
{
|
{
|
||||||
(void)file_options;
|
(void)file_options;
|
||||||
|
(void)size;
|
||||||
void (*memfree)(void*, void*) = memory_options->free_func ? memory_options->free_func : &cgltf_default_free;
|
void (*memfree)(void*, void*) = memory_options->free_func ? memory_options->free_func : &cgltf_default_free;
|
||||||
memfree(memory_options->user_data, data);
|
memfree(memory_options->user_data, data);
|
||||||
}
|
}
|
||||||
|
|
@ -1220,7 +1252,7 @@ cgltf_result cgltf_parse_file(const cgltf_options* options, const char* path, cg
|
||||||
}
|
}
|
||||||
|
|
||||||
cgltf_result (*file_read)(const struct cgltf_memory_options*, const struct cgltf_file_options*, const char*, cgltf_size*, void**) = options->file.read ? options->file.read : &cgltf_default_file_read;
|
cgltf_result (*file_read)(const struct cgltf_memory_options*, const struct cgltf_file_options*, const char*, cgltf_size*, void**) = options->file.read ? options->file.read : &cgltf_default_file_read;
|
||||||
void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data) = options->file.release ? options->file.release : cgltf_default_file_release;
|
void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data, cgltf_size size) = options->file.release ? options->file.release : cgltf_default_file_release;
|
||||||
|
|
||||||
void* file_data = NULL;
|
void* file_data = NULL;
|
||||||
cgltf_size file_size = 0;
|
cgltf_size file_size = 0;
|
||||||
|
|
@ -1234,11 +1266,12 @@ cgltf_result cgltf_parse_file(const cgltf_options* options, const char* path, cg
|
||||||
|
|
||||||
if (result != cgltf_result_success)
|
if (result != cgltf_result_success)
|
||||||
{
|
{
|
||||||
file_release(&options->memory, &options->file, file_data);
|
file_release(&options->memory, &options->file, file_data, file_size);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
(*out_data)->file_data = file_data;
|
(*out_data)->file_data = file_data;
|
||||||
|
(*out_data)->file_size = file_size;
|
||||||
|
|
||||||
return cgltf_result_success;
|
return cgltf_result_success;
|
||||||
}
|
}
|
||||||
|
|
@ -1630,8 +1663,8 @@ cgltf_result cgltf_validate(cgltf_data* data)
|
||||||
CGLTF_ASSERT_IF((mc->mode == cgltf_meshopt_compression_mode_triangles || mc->mode == cgltf_meshopt_compression_mode_indices) && mc->filter != cgltf_meshopt_compression_filter_none, cgltf_result_invalid_gltf);
|
CGLTF_ASSERT_IF((mc->mode == cgltf_meshopt_compression_mode_triangles || mc->mode == cgltf_meshopt_compression_mode_indices) && mc->filter != cgltf_meshopt_compression_filter_none, cgltf_result_invalid_gltf);
|
||||||
|
|
||||||
CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_octahedral && mc->stride != 4 && mc->stride != 8, cgltf_result_invalid_gltf);
|
CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_octahedral && mc->stride != 4 && mc->stride != 8, cgltf_result_invalid_gltf);
|
||||||
|
|
||||||
CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_quaternion && mc->stride != 8, cgltf_result_invalid_gltf);
|
CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_quaternion && mc->stride != 8, cgltf_result_invalid_gltf);
|
||||||
|
CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_color && mc->stride != 4 && mc->stride != 8, cgltf_result_invalid_gltf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1822,7 +1855,7 @@ void cgltf_free(cgltf_data* data)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data) = data->file.release ? data->file.release : cgltf_default_file_release;
|
void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data, cgltf_size size) = data->file.release ? data->file.release : cgltf_default_file_release;
|
||||||
|
|
||||||
data->memory.free_func(data->memory.user_data, data->asset.copyright);
|
data->memory.free_func(data->memory.user_data, data->asset.copyright);
|
||||||
data->memory.free_func(data->memory.user_data, data->asset.generator);
|
data->memory.free_func(data->memory.user_data, data->asset.generator);
|
||||||
|
|
@ -1857,7 +1890,7 @@ void cgltf_free(cgltf_data* data)
|
||||||
|
|
||||||
if (data->buffers[i].data_free_method == cgltf_data_free_method_file_release)
|
if (data->buffers[i].data_free_method == cgltf_data_free_method_file_release)
|
||||||
{
|
{
|
||||||
file_release(&data->memory, &data->file, data->buffers[i].data);
|
file_release(&data->memory, &data->file, data->buffers[i].data, data->buffers[i].size);
|
||||||
}
|
}
|
||||||
else if (data->buffers[i].data_free_method == cgltf_data_free_method_memory_free)
|
else if (data->buffers[i].data_free_method == cgltf_data_free_method_memory_free)
|
||||||
{
|
{
|
||||||
|
|
@ -2096,7 +2129,7 @@ void cgltf_free(cgltf_data* data)
|
||||||
|
|
||||||
data->memory.free_func(data->memory.user_data, data->extensions_required);
|
data->memory.free_func(data->memory.user_data, data->extensions_required);
|
||||||
|
|
||||||
file_release(&data->memory, &data->file, data->file_data);
|
file_release(&data->memory, &data->file, data->file_data, data->file_size);
|
||||||
|
|
||||||
data->memory.free_func(data->memory.user_data, data);
|
data->memory.free_func(data->memory.user_data, data);
|
||||||
}
|
}
|
||||||
|
|
@ -2312,11 +2345,58 @@ const uint8_t* cgltf_buffer_view_data(const cgltf_buffer_view* view)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cgltf_accessor* cgltf_find_accessor(const cgltf_primitive* prim, cgltf_attribute_type type, cgltf_int index)
|
||||||
|
{
|
||||||
|
for (cgltf_size i = 0; i < prim->attributes_count; ++i)
|
||||||
|
{
|
||||||
|
const cgltf_attribute* attr = &prim->attributes[i];
|
||||||
|
if (attr->type == type && attr->index == index)
|
||||||
|
return attr->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const uint8_t* cgltf_find_sparse_index(const cgltf_accessor* accessor, cgltf_size needle)
|
||||||
|
{
|
||||||
|
const cgltf_accessor_sparse* sparse = &accessor->sparse;
|
||||||
|
const uint8_t* index_data = cgltf_buffer_view_data(sparse->indices_buffer_view);
|
||||||
|
const uint8_t* value_data = cgltf_buffer_view_data(sparse->values_buffer_view);
|
||||||
|
|
||||||
|
if (index_data == NULL || value_data == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
index_data += sparse->indices_byte_offset;
|
||||||
|
value_data += sparse->values_byte_offset;
|
||||||
|
|
||||||
|
cgltf_size index_stride = cgltf_component_size(sparse->indices_component_type);
|
||||||
|
|
||||||
|
cgltf_size offset = 0;
|
||||||
|
cgltf_size length = sparse->count;
|
||||||
|
|
||||||
|
while (length)
|
||||||
|
{
|
||||||
|
cgltf_size rem = length % 2;
|
||||||
|
length /= 2;
|
||||||
|
|
||||||
|
cgltf_size index = cgltf_component_read_index(index_data + (offset + length) * index_stride, sparse->indices_component_type);
|
||||||
|
offset += index < needle ? length + rem : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset == sparse->count)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
cgltf_size index = cgltf_component_read_index(index_data + offset * index_stride, sparse->indices_component_type);
|
||||||
|
return index == needle ? value_data + offset * accessor->stride : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size)
|
cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size)
|
||||||
{
|
{
|
||||||
if (accessor->is_sparse)
|
if (accessor->is_sparse)
|
||||||
{
|
{
|
||||||
return 0;
|
const uint8_t* element = cgltf_find_sparse_index(accessor, index);
|
||||||
|
if (element)
|
||||||
|
return cgltf_element_read_float(element, accessor->type, accessor->component_type, accessor->normalized, out, element_size);
|
||||||
}
|
}
|
||||||
if (accessor->buffer_view == NULL)
|
if (accessor->buffer_view == NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -2460,11 +2540,13 @@ cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size i
|
||||||
{
|
{
|
||||||
if (accessor->is_sparse)
|
if (accessor->is_sparse)
|
||||||
{
|
{
|
||||||
return 0;
|
const uint8_t* element = cgltf_find_sparse_index(accessor, index);
|
||||||
|
if (element)
|
||||||
|
return cgltf_element_read_uint(element, accessor->type, accessor->component_type, out, element_size);
|
||||||
}
|
}
|
||||||
if (accessor->buffer_view == NULL)
|
if (accessor->buffer_view == NULL)
|
||||||
{
|
{
|
||||||
memset(out, 0, element_size * sizeof( cgltf_uint ));
|
memset(out, 0, element_size * sizeof(cgltf_uint));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
|
const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
|
||||||
|
|
@ -2480,7 +2562,9 @@ cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size
|
||||||
{
|
{
|
||||||
if (accessor->is_sparse)
|
if (accessor->is_sparse)
|
||||||
{
|
{
|
||||||
return 0; // This is an error case, but we can't communicate the error with existing interface.
|
const uint8_t* element = cgltf_find_sparse_index(accessor, index);
|
||||||
|
if (element)
|
||||||
|
return cgltf_component_read_index(element, accessor->component_type);
|
||||||
}
|
}
|
||||||
if (accessor->buffer_view == NULL)
|
if (accessor->buffer_view == NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -2598,7 +2682,10 @@ cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor* accessor, void* o
|
||||||
return accessor->count;
|
return accessor->count;
|
||||||
}
|
}
|
||||||
|
|
||||||
index_count = accessor->count < index_count ? accessor->count : index_count;
|
cgltf_size numbers_per_element = cgltf_num_components(accessor->type);
|
||||||
|
cgltf_size available_numbers = accessor->count * numbers_per_element;
|
||||||
|
|
||||||
|
index_count = available_numbers < index_count ? available_numbers : index_count;
|
||||||
cgltf_size index_component_size = cgltf_component_size(accessor->component_type);
|
cgltf_size index_component_size = cgltf_component_size(accessor->component_type);
|
||||||
|
|
||||||
if (accessor->is_sparse)
|
if (accessor->is_sparse)
|
||||||
|
|
@ -2620,15 +2707,23 @@ cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor* accessor, void* o
|
||||||
}
|
}
|
||||||
element += accessor->offset;
|
element += accessor->offset;
|
||||||
|
|
||||||
if (index_component_size == out_component_size && accessor->stride == out_component_size)
|
if (index_component_size == out_component_size && accessor->stride == out_component_size * numbers_per_element)
|
||||||
{
|
{
|
||||||
memcpy(out, element, index_count * index_component_size);
|
memcpy(out, element, index_count * index_component_size);
|
||||||
return index_count;
|
return index_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Data couldn't be copied with memcpy due to stride being larger than the component size.
|
||||||
|
// OR
|
||||||
// The component size of the output array is larger than the component size of the index data, so index data will be padded.
|
// The component size of the output array is larger than the component size of the index data, so index data will be padded.
|
||||||
switch (out_component_size)
|
switch (out_component_size)
|
||||||
{
|
{
|
||||||
|
case 1:
|
||||||
|
for (cgltf_size index = 0; index < index_count; index++, element += accessor->stride)
|
||||||
|
{
|
||||||
|
((uint8_t*)out)[index] = (uint8_t)cgltf_component_read_index(element, accessor->component_type);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
for (cgltf_size index = 0; index < index_count; index++, element += accessor->stride)
|
for (cgltf_size index = 0; index < index_count; index++, element += accessor->stride)
|
||||||
{
|
{
|
||||||
|
|
@ -2642,7 +2737,7 @@ cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor* accessor, void* o
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return index_count;
|
return index_count;
|
||||||
|
|
@ -4278,6 +4373,52 @@ static int cgltf_parse_json_iridescence(cgltf_options* options, jsmntok_t const*
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cgltf_parse_json_diffuse_transmission(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_diffuse_transmission* out_diff_transmission)
|
||||||
|
{
|
||||||
|
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
||||||
|
int size = tokens[i].size;
|
||||||
|
++i;
|
||||||
|
|
||||||
|
// Defaults
|
||||||
|
cgltf_fill_float_array(out_diff_transmission->diffuse_transmission_color_factor, 3, 1.0f);
|
||||||
|
out_diff_transmission->diffuse_transmission_factor = 0.f;
|
||||||
|
|
||||||
|
for (int j = 0; j < size; ++j)
|
||||||
|
{
|
||||||
|
CGLTF_CHECK_KEY(tokens[i]);
|
||||||
|
|
||||||
|
if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionFactor") == 0)
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
out_diff_transmission->diffuse_transmission_factor = cgltf_json_to_float(tokens + i, json_chunk);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
else if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionTexture") == 0)
|
||||||
|
{
|
||||||
|
i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_diff_transmission->diffuse_transmission_texture);
|
||||||
|
}
|
||||||
|
else if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionColorFactor") == 0)
|
||||||
|
{
|
||||||
|
i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_diff_transmission->diffuse_transmission_color_factor, 3);
|
||||||
|
}
|
||||||
|
else if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionColorTexture") == 0)
|
||||||
|
{
|
||||||
|
i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_diff_transmission->diffuse_transmission_color_texture);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i = cgltf_skip_json(tokens, i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < 0)
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
static int cgltf_parse_json_anisotropy(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_anisotropy* out_anisotropy)
|
static int cgltf_parse_json_anisotropy(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_anisotropy* out_anisotropy)
|
||||||
{
|
{
|
||||||
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
||||||
|
|
@ -4406,8 +4547,8 @@ static int cgltf_parse_json_sampler(cgltf_options* options, jsmntok_t const* tok
|
||||||
(void)options;
|
(void)options;
|
||||||
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
||||||
|
|
||||||
out_sampler->wrap_s = 10497;
|
out_sampler->wrap_s = cgltf_wrap_mode_repeat;
|
||||||
out_sampler->wrap_t = 10497;
|
out_sampler->wrap_t = cgltf_wrap_mode_repeat;
|
||||||
|
|
||||||
int size = tokens[i].size;
|
int size = tokens[i].size;
|
||||||
++i;
|
++i;
|
||||||
|
|
@ -4424,28 +4565,28 @@ static int cgltf_parse_json_sampler(cgltf_options* options, jsmntok_t const* tok
|
||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
out_sampler->mag_filter
|
out_sampler->mag_filter
|
||||||
= cgltf_json_to_int(tokens + i, json_chunk);
|
= (cgltf_filter_type)cgltf_json_to_int(tokens + i, json_chunk);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "minFilter") == 0)
|
else if (cgltf_json_strcmp(tokens + i, json_chunk, "minFilter") == 0)
|
||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
out_sampler->min_filter
|
out_sampler->min_filter
|
||||||
= cgltf_json_to_int(tokens + i, json_chunk);
|
= (cgltf_filter_type)cgltf_json_to_int(tokens + i, json_chunk);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapS") == 0)
|
else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapS") == 0)
|
||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
out_sampler->wrap_s
|
out_sampler->wrap_s
|
||||||
= cgltf_json_to_int(tokens + i, json_chunk);
|
= (cgltf_wrap_mode)cgltf_json_to_int(tokens + i, json_chunk);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapT") == 0)
|
else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapT") == 0)
|
||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
out_sampler->wrap_t
|
out_sampler->wrap_t
|
||||||
= cgltf_json_to_int(tokens + i, json_chunk);
|
= (cgltf_wrap_mode)cgltf_json_to_int(tokens + i, json_chunk);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
|
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
|
||||||
|
|
@ -4766,6 +4907,11 @@ static int cgltf_parse_json_material(cgltf_options* options, jsmntok_t const* to
|
||||||
out_material->has_iridescence = 1;
|
out_material->has_iridescence = 1;
|
||||||
i = cgltf_parse_json_iridescence(options, tokens, i + 1, json_chunk, &out_material->iridescence);
|
i = cgltf_parse_json_iridescence(options, tokens, i + 1, json_chunk, &out_material->iridescence);
|
||||||
}
|
}
|
||||||
|
else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_diffuse_transmission") == 0)
|
||||||
|
{
|
||||||
|
out_material->has_diffuse_transmission = 1;
|
||||||
|
i = cgltf_parse_json_diffuse_transmission(options, tokens, i + 1, json_chunk, &out_material->diffuse_transmission);
|
||||||
|
}
|
||||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_anisotropy") == 0)
|
else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_anisotropy") == 0)
|
||||||
{
|
{
|
||||||
out_material->has_anisotropy = 1;
|
out_material->has_anisotropy = 1;
|
||||||
|
|
@ -4974,6 +5120,10 @@ static int cgltf_parse_json_meshopt_compression(cgltf_options* options, jsmntok_
|
||||||
{
|
{
|
||||||
out_meshopt_compression->filter = cgltf_meshopt_compression_filter_exponential;
|
out_meshopt_compression->filter = cgltf_meshopt_compression_filter_exponential;
|
||||||
}
|
}
|
||||||
|
else if (cgltf_json_strcmp(tokens+i, json_chunk, "COLOR") == 0)
|
||||||
|
{
|
||||||
|
out_meshopt_compression->filter = cgltf_meshopt_compression_filter_color;
|
||||||
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -5084,6 +5234,12 @@ static int cgltf_parse_json_buffer_view(cgltf_options* options, jsmntok_t const*
|
||||||
out_buffer_view->has_meshopt_compression = 1;
|
out_buffer_view->has_meshopt_compression = 1;
|
||||||
i = cgltf_parse_json_meshopt_compression(options, tokens, i + 1, json_chunk, &out_buffer_view->meshopt_compression);
|
i = cgltf_parse_json_meshopt_compression(options, tokens, i + 1, json_chunk, &out_buffer_view->meshopt_compression);
|
||||||
}
|
}
|
||||||
|
else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_meshopt_compression") == 0)
|
||||||
|
{
|
||||||
|
out_buffer_view->has_meshopt_compression = 1;
|
||||||
|
out_buffer_view->meshopt_compression.is_khr = 1;
|
||||||
|
i = cgltf_parse_json_meshopt_compression(options, tokens, i + 1, json_chunk, &out_buffer_view->meshopt_compression);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_buffer_view->extensions[out_buffer_view->extensions_count++]));
|
i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_buffer_view->extensions[out_buffer_view->extensions_count++]));
|
||||||
|
|
@ -6629,6 +6785,9 @@ static int cgltf_fixup_pointers(cgltf_data* data)
|
||||||
CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_texture.texture, data->textures, data->textures_count);
|
CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_texture.texture, data->textures, data->textures_count);
|
||||||
CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_thickness_texture.texture, data->textures, data->textures_count);
|
CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_thickness_texture.texture, data->textures, data->textures_count);
|
||||||
|
|
||||||
|
CGLTF_PTRFIXUP(data->materials[i].diffuse_transmission.diffuse_transmission_texture.texture, data->textures, data->textures_count);
|
||||||
|
CGLTF_PTRFIXUP(data->materials[i].diffuse_transmission.diffuse_transmission_color_texture.texture, data->textures, data->textures_count);
|
||||||
|
|
||||||
CGLTF_PTRFIXUP(data->materials[i].anisotropy.anisotropy_texture.texture, data->textures, data->textures_count);
|
CGLTF_PTRFIXUP(data->materials[i].anisotropy.anisotropy_texture.texture, data->textures, data->textures_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
1565
src/external/cgltf_write.h
vendored
Normal file
1565
src/external/cgltf_write.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
306
src/external/dr_flac.h
vendored
306
src/external/dr_flac.h
vendored
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
FLAC audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
|
FLAC audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
|
||||||
dr_flac - v0.13.0 - TBD
|
dr_flac - v0.13.3 - 2026-01-17
|
||||||
|
|
||||||
David Reid - mackron@gmail.com
|
David Reid - mackron@gmail.com
|
||||||
|
|
||||||
|
|
@ -126,7 +126,7 @@ extern "C" {
|
||||||
|
|
||||||
#define DRFLAC_VERSION_MAJOR 0
|
#define DRFLAC_VERSION_MAJOR 0
|
||||||
#define DRFLAC_VERSION_MINOR 13
|
#define DRFLAC_VERSION_MINOR 13
|
||||||
#define DRFLAC_VERSION_REVISION 0
|
#define DRFLAC_VERSION_REVISION 3
|
||||||
#define DRFLAC_VERSION_STRING DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MAJOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MINOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_REVISION)
|
#define DRFLAC_VERSION_STRING DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MAJOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MINOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_REVISION)
|
||||||
|
|
||||||
#include <stddef.h> /* For size_t. */
|
#include <stddef.h> /* For size_t. */
|
||||||
|
|
@ -331,6 +331,12 @@ typedef struct
|
||||||
*/
|
*/
|
||||||
drflac_uint32 type;
|
drflac_uint32 type;
|
||||||
|
|
||||||
|
/* The size in bytes of the block and the buffer pointed to by pRawData if it's non-NULL. */
|
||||||
|
drflac_uint32 rawDataSize;
|
||||||
|
|
||||||
|
/* The offset in the stream of the raw data. */
|
||||||
|
drflac_uint64 rawDataOffset;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A pointer to the raw data. This points to a temporary buffer so don't hold on to it. It's best to
|
A pointer to the raw data. This points to a temporary buffer so don't hold on to it. It's best to
|
||||||
not modify the contents of this buffer. Use the structures below for more meaningful and structured
|
not modify the contents of this buffer. Use the structures below for more meaningful and structured
|
||||||
|
|
@ -338,9 +344,6 @@ typedef struct
|
||||||
*/
|
*/
|
||||||
const void* pRawData;
|
const void* pRawData;
|
||||||
|
|
||||||
/* The size in bytes of the block and the buffer pointed to by pRawData if it's non-NULL. */
|
|
||||||
drflac_uint32 rawDataSize;
|
|
||||||
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
drflac_streaminfo streaminfo;
|
drflac_streaminfo streaminfo;
|
||||||
|
|
@ -392,6 +395,7 @@ typedef struct
|
||||||
drflac_uint32 colorDepth;
|
drflac_uint32 colorDepth;
|
||||||
drflac_uint32 indexColorCount;
|
drflac_uint32 indexColorCount;
|
||||||
drflac_uint32 pictureDataSize;
|
drflac_uint32 pictureDataSize;
|
||||||
|
drflac_uint64 pictureDataOffset; /* Offset from the start of the stream. */
|
||||||
const drflac_uint8* pPictureData;
|
const drflac_uint8* pPictureData;
|
||||||
} picture;
|
} picture;
|
||||||
} data;
|
} data;
|
||||||
|
|
@ -2712,9 +2716,17 @@ static DRFLAC_INLINE drflac_uint32 drflac__clz_lzcnt(drflac_cache_t x)
|
||||||
#if defined(__GNUC__) || defined(__clang__)
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
#if defined(DRFLAC_X64)
|
#if defined(DRFLAC_X64)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
A note on lzcnt.
|
||||||
|
|
||||||
|
We check for the presence of the lzcnt instruction at runtime before calling this function, but we still generate this code. I have had
|
||||||
|
a report where the assembler does not recognize the lzcnt instruction. To work around this we are going to use `rep; bsr` instead which
|
||||||
|
has an identical byte encoding as lzcnt, and should hopefully improve compatibility with older assemblers.
|
||||||
|
*/
|
||||||
drflac_uint64 r;
|
drflac_uint64 r;
|
||||||
__asm__ __volatile__ (
|
__asm__ __volatile__ (
|
||||||
"lzcnt{ %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"
|
"rep; bsr{q %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"
|
||||||
|
/*"lzcnt{ %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"*/
|
||||||
);
|
);
|
||||||
|
|
||||||
return (drflac_uint32)r;
|
return (drflac_uint32)r;
|
||||||
|
|
@ -2723,12 +2735,13 @@ static DRFLAC_INLINE drflac_uint32 drflac__clz_lzcnt(drflac_cache_t x)
|
||||||
{
|
{
|
||||||
drflac_uint32 r;
|
drflac_uint32 r;
|
||||||
__asm__ __volatile__ (
|
__asm__ __volatile__ (
|
||||||
"lzcnt{l %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"
|
"rep; bsr{l %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"
|
||||||
|
/*"lzcnt{l %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"*/
|
||||||
);
|
);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
#elif defined(DRFLAC_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 5) && !defined(__ARM_ARCH_6M__) && !defined(DRFLAC_64BIT) /* <-- I haven't tested 64-bit inline assembly, so only enabling this for the 32-bit build for now. */
|
#elif defined(DRFLAC_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 5) && !defined(__ARM_ARCH_6M__) && !(defined(__thumb__) && !defined(__thumb2__)) && !defined(DRFLAC_64BIT) /* <-- I haven't tested 64-bit inline assembly, so only enabling this for the 32-bit build for now. */
|
||||||
{
|
{
|
||||||
unsigned int r;
|
unsigned int r;
|
||||||
__asm__ __volatile__ (
|
__asm__ __volatile__ (
|
||||||
|
|
@ -6434,8 +6447,9 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
||||||
runningFilePos += 4;
|
runningFilePos += 4;
|
||||||
|
|
||||||
metadata.type = blockType;
|
metadata.type = blockType;
|
||||||
metadata.pRawData = NULL;
|
|
||||||
metadata.rawDataSize = 0;
|
metadata.rawDataSize = 0;
|
||||||
|
metadata.rawDataOffset = runningFilePos;
|
||||||
|
metadata.pRawData = NULL;
|
||||||
|
|
||||||
switch (blockType)
|
switch (blockType)
|
||||||
{
|
{
|
||||||
|
|
@ -6712,59 +6726,151 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onMeta) {
|
if (onMeta) {
|
||||||
void* pRawData;
|
drflac_bool32 result = DRFLAC_TRUE;
|
||||||
const char* pRunningData;
|
drflac_uint32 blockSizeRemaining = blockSize;
|
||||||
const char* pRunningDataEnd;
|
char* pMime = NULL;
|
||||||
|
char* pDescription = NULL;
|
||||||
|
void* pPictureData = NULL;
|
||||||
|
|
||||||
pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
|
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.type, 4) != 4) {
|
||||||
if (pRawData == NULL) {
|
result = DRFLAC_FALSE;
|
||||||
return DRFLAC_FALSE;
|
goto done_flac;
|
||||||
|
}
|
||||||
|
blockSizeRemaining -= 4;
|
||||||
|
metadata.data.picture.type = drflac__be2host_32(metadata.data.picture.type);
|
||||||
|
|
||||||
|
|
||||||
|
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.mimeLength, 4) != 4) {
|
||||||
|
result = DRFLAC_FALSE;
|
||||||
|
goto done_flac;
|
||||||
|
}
|
||||||
|
blockSizeRemaining -= 4;
|
||||||
|
metadata.data.picture.mimeLength = drflac__be2host_32(metadata.data.picture.mimeLength);
|
||||||
|
|
||||||
|
pMime = (char*)drflac__malloc_from_callbacks(metadata.data.picture.mimeLength + 1, pAllocationCallbacks); /* +1 for null terminator. */
|
||||||
|
if (pMime == NULL) {
|
||||||
|
result = DRFLAC_FALSE;
|
||||||
|
goto done_flac;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onRead(pUserData, pRawData, blockSize) != blockSize) {
|
if (blockSizeRemaining < metadata.data.picture.mimeLength || onRead(pUserData, pMime, metadata.data.picture.mimeLength) != metadata.data.picture.mimeLength) {
|
||||||
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
result = DRFLAC_FALSE;
|
||||||
return DRFLAC_FALSE;
|
goto done_flac;
|
||||||
|
}
|
||||||
|
blockSizeRemaining -= metadata.data.picture.mimeLength;
|
||||||
|
pMime[metadata.data.picture.mimeLength] = '\0'; /* Null terminate for safety. */
|
||||||
|
metadata.data.picture.mime = (const char*)pMime;
|
||||||
|
|
||||||
|
|
||||||
|
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.descriptionLength, 4) != 4) {
|
||||||
|
result = DRFLAC_FALSE;
|
||||||
|
goto done_flac;
|
||||||
|
}
|
||||||
|
blockSizeRemaining -= 4;
|
||||||
|
metadata.data.picture.descriptionLength = drflac__be2host_32(metadata.data.picture.descriptionLength);
|
||||||
|
|
||||||
|
pDescription = (char*)drflac__malloc_from_callbacks(metadata.data.picture.descriptionLength + 1, pAllocationCallbacks); /* +1 for null terminator. */
|
||||||
|
if (pDescription == NULL) {
|
||||||
|
result = DRFLAC_FALSE;
|
||||||
|
goto done_flac;
|
||||||
}
|
}
|
||||||
|
|
||||||
metadata.pRawData = pRawData;
|
if (blockSizeRemaining < metadata.data.picture.descriptionLength || onRead(pUserData, pDescription, metadata.data.picture.descriptionLength) != metadata.data.picture.descriptionLength) {
|
||||||
metadata.rawDataSize = blockSize;
|
result = DRFLAC_FALSE;
|
||||||
|
goto done_flac;
|
||||||
pRunningData = (const char*)pRawData;
|
|
||||||
pRunningDataEnd = (const char*)pRawData + blockSize;
|
|
||||||
|
|
||||||
metadata.data.picture.type = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
|
||||||
metadata.data.picture.mimeLength = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
|
||||||
|
|
||||||
/* Need space for the rest of the block */
|
|
||||||
if ((pRunningDataEnd - pRunningData) - 24 < (drflac_int64)metadata.data.picture.mimeLength) { /* <-- Note the order of operations to avoid overflow to a valid value */
|
|
||||||
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
|
||||||
return DRFLAC_FALSE;
|
|
||||||
}
|
}
|
||||||
metadata.data.picture.mime = pRunningData; pRunningData += metadata.data.picture.mimeLength;
|
blockSizeRemaining -= metadata.data.picture.descriptionLength;
|
||||||
metadata.data.picture.descriptionLength = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
pDescription[metadata.data.picture.descriptionLength] = '\0'; /* Null terminate for safety. */
|
||||||
|
metadata.data.picture.description = (const char*)pDescription;
|
||||||
|
|
||||||
/* Need space for the rest of the block */
|
|
||||||
if ((pRunningDataEnd - pRunningData) - 20 < (drflac_int64)metadata.data.picture.descriptionLength) { /* <-- Note the order of operations to avoid overflow to a valid value */
|
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.width, 4) != 4) {
|
||||||
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
result = DRFLAC_FALSE;
|
||||||
return DRFLAC_FALSE;
|
goto done_flac;
|
||||||
}
|
}
|
||||||
metadata.data.picture.description = pRunningData; pRunningData += metadata.data.picture.descriptionLength;
|
blockSizeRemaining -= 4;
|
||||||
metadata.data.picture.width = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
metadata.data.picture.width = drflac__be2host_32(metadata.data.picture.width);
|
||||||
metadata.data.picture.height = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
|
||||||
metadata.data.picture.colorDepth = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
|
||||||
metadata.data.picture.indexColorCount = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
|
||||||
metadata.data.picture.pictureDataSize = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
|
||||||
metadata.data.picture.pPictureData = (const drflac_uint8*)pRunningData;
|
|
||||||
|
|
||||||
/* Need space for the picture after the block */
|
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.height, 4) != 4) {
|
||||||
if (pRunningDataEnd - pRunningData < (drflac_int64)metadata.data.picture.pictureDataSize) { /* <-- Note the order of operations to avoid overflow to a valid value */
|
result = DRFLAC_FALSE;
|
||||||
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
goto done_flac;
|
||||||
return DRFLAC_FALSE;
|
}
|
||||||
|
blockSizeRemaining -= 4;
|
||||||
|
metadata.data.picture.height = drflac__be2host_32(metadata.data.picture.height);
|
||||||
|
|
||||||
|
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.colorDepth, 4) != 4) {
|
||||||
|
result = DRFLAC_FALSE;
|
||||||
|
goto done_flac;
|
||||||
|
}
|
||||||
|
blockSizeRemaining -= 4;
|
||||||
|
metadata.data.picture.colorDepth = drflac__be2host_32(metadata.data.picture.colorDepth);
|
||||||
|
|
||||||
|
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.indexColorCount, 4) != 4) {
|
||||||
|
result = DRFLAC_FALSE;
|
||||||
|
goto done_flac;
|
||||||
|
}
|
||||||
|
blockSizeRemaining -= 4;
|
||||||
|
metadata.data.picture.indexColorCount = drflac__be2host_32(metadata.data.picture.indexColorCount);
|
||||||
|
|
||||||
|
|
||||||
|
/* Picture data. */
|
||||||
|
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.pictureDataSize, 4) != 4) {
|
||||||
|
result = DRFLAC_FALSE;
|
||||||
|
goto done_flac;
|
||||||
|
}
|
||||||
|
blockSizeRemaining -= 4;
|
||||||
|
metadata.data.picture.pictureDataSize = drflac__be2host_32(metadata.data.picture.pictureDataSize);
|
||||||
|
|
||||||
|
if (blockSizeRemaining < metadata.data.picture.pictureDataSize) {
|
||||||
|
result = DRFLAC_FALSE;
|
||||||
|
goto done_flac;
|
||||||
}
|
}
|
||||||
|
|
||||||
onMeta(pUserDataMD, &metadata);
|
/* For the actual image data we want to store the offset to the start of the stream. */
|
||||||
|
metadata.data.picture.pictureDataOffset = runningFilePos + (blockSize - blockSizeRemaining);
|
||||||
|
|
||||||
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
/*
|
||||||
|
For the allocation of image data, we can allow memory allocation to fail, in which case we just leave
|
||||||
|
the pointer as null. If it fails, we need to fall back to seeking past the image data.
|
||||||
|
*/
|
||||||
|
#ifndef DR_FLAC_NO_PICTURE_METADATA_MALLOC
|
||||||
|
pPictureData = drflac__malloc_from_callbacks(metadata.data.picture.pictureDataSize, pAllocationCallbacks);
|
||||||
|
if (pPictureData != NULL) {
|
||||||
|
if (onRead(pUserData, pPictureData, metadata.data.picture.pictureDataSize) != metadata.data.picture.pictureDataSize) {
|
||||||
|
result = DRFLAC_FALSE;
|
||||||
|
goto done_flac;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* Allocation failed. We need to seek past the picture data. */
|
||||||
|
if (!onSeek(pUserData, metadata.data.picture.pictureDataSize, DRFLAC_SEEK_CUR)) {
|
||||||
|
result = DRFLAC_FALSE;
|
||||||
|
goto done_flac;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockSizeRemaining -= metadata.data.picture.pictureDataSize;
|
||||||
|
(void)blockSizeRemaining;
|
||||||
|
|
||||||
|
metadata.data.picture.pPictureData = (const drflac_uint8*)pPictureData;
|
||||||
|
|
||||||
|
|
||||||
|
/* Only fire the callback if we actually have a way to read the image data. We must have either a valid offset, or a valid data pointer. */
|
||||||
|
if (metadata.data.picture.pictureDataOffset != 0 || metadata.data.picture.pPictureData != NULL) {
|
||||||
|
onMeta(pUserDataMD, &metadata);
|
||||||
|
} else {
|
||||||
|
/* Don't have a valid offset or data pointer, so just pretend we don't have a picture metadata. */
|
||||||
|
}
|
||||||
|
|
||||||
|
done_flac:
|
||||||
|
drflac__free_from_callbacks(pMime, pAllocationCallbacks);
|
||||||
|
drflac__free_from_callbacks(pDescription, pAllocationCallbacks);
|
||||||
|
drflac__free_from_callbacks(pPictureData, pAllocationCallbacks);
|
||||||
|
|
||||||
|
if (result != DRFLAC_TRUE) {
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|
@ -6800,13 +6906,16 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
||||||
*/
|
*/
|
||||||
if (onMeta) {
|
if (onMeta) {
|
||||||
void* pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
|
void* pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
|
||||||
if (pRawData == NULL) {
|
if (pRawData != NULL) {
|
||||||
return DRFLAC_FALSE;
|
if (onRead(pUserData, pRawData, blockSize) != blockSize) {
|
||||||
}
|
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
||||||
|
return DRFLAC_FALSE;
|
||||||
if (onRead(pUserData, pRawData, blockSize) != blockSize) {
|
}
|
||||||
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
} else {
|
||||||
return DRFLAC_FALSE;
|
/* Allocation failed. We need to seek past the block. */
|
||||||
|
if (!onSeek(pUserData, blockSize, DRFLAC_SEEK_CUR)) {
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
metadata.pRawData = pRawData;
|
metadata.pRawData = pRawData;
|
||||||
|
|
@ -8699,7 +8808,7 @@ static drflac_bool32 drflac__on_tell_stdio(void* pUserData, drflac_int64* pCurso
|
||||||
DRFLAC_ASSERT(pFileStdio != NULL);
|
DRFLAC_ASSERT(pFileStdio != NULL);
|
||||||
DRFLAC_ASSERT(pCursor != NULL);
|
DRFLAC_ASSERT(pCursor != NULL);
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32) && !defined(NXDK)
|
||||||
#if defined(_MSC_VER) && _MSC_VER > 1200
|
#if defined(_MSC_VER) && _MSC_VER > 1200
|
||||||
result = _ftelli64(pFileStdio);
|
result = _ftelli64(pFileStdio);
|
||||||
#else
|
#else
|
||||||
|
|
@ -8821,8 +8930,6 @@ static drflac_bool32 drflac__on_seek_memory(void* pUserData, int offset, drflac_
|
||||||
|
|
||||||
DRFLAC_ASSERT(memoryStream != NULL);
|
DRFLAC_ASSERT(memoryStream != NULL);
|
||||||
|
|
||||||
newCursor = memoryStream->currentReadPos;
|
|
||||||
|
|
||||||
if (origin == DRFLAC_SEEK_SET) {
|
if (origin == DRFLAC_SEEK_SET) {
|
||||||
newCursor = 0;
|
newCursor = 0;
|
||||||
} else if (origin == DRFLAC_SEEK_CUR) {
|
} else if (origin == DRFLAC_SEEK_CUR) {
|
||||||
|
|
@ -11702,58 +11809,43 @@ static type* drflac__full_read_and_close_ ## extension (drflac* pFlac, unsigned
|
||||||
{ \
|
{ \
|
||||||
type* pSampleData = NULL; \
|
type* pSampleData = NULL; \
|
||||||
drflac_uint64 totalPCMFrameCount; \
|
drflac_uint64 totalPCMFrameCount; \
|
||||||
|
type buffer[4096]; \
|
||||||
|
drflac_uint64 pcmFramesRead; \
|
||||||
|
size_t sampleDataBufferSize = sizeof(buffer); \
|
||||||
\
|
\
|
||||||
DRFLAC_ASSERT(pFlac != NULL); \
|
DRFLAC_ASSERT(pFlac != NULL); \
|
||||||
\
|
\
|
||||||
totalPCMFrameCount = pFlac->totalPCMFrameCount; \
|
totalPCMFrameCount = 0; \
|
||||||
\
|
\
|
||||||
if (totalPCMFrameCount == 0) { \
|
pSampleData = (type*)drflac__malloc_from_callbacks(sampleDataBufferSize, &pFlac->allocationCallbacks); \
|
||||||
type buffer[4096]; \
|
if (pSampleData == NULL) { \
|
||||||
drflac_uint64 pcmFramesRead; \
|
goto on_error; \
|
||||||
size_t sampleDataBufferSize = sizeof(buffer); \
|
} \
|
||||||
\
|
\
|
||||||
pSampleData = (type*)drflac__malloc_from_callbacks(sampleDataBufferSize, &pFlac->allocationCallbacks); \
|
while ((pcmFramesRead = (drflac_uint64)drflac_read_pcm_frames_##extension(pFlac, sizeof(buffer)/sizeof(buffer[0])/pFlac->channels, buffer)) > 0) { \
|
||||||
if (pSampleData == NULL) { \
|
if (((totalPCMFrameCount + pcmFramesRead) * pFlac->channels * sizeof(type)) > sampleDataBufferSize) { \
|
||||||
goto on_error; \
|
type* pNewSampleData; \
|
||||||
} \
|
size_t newSampleDataBufferSize; \
|
||||||
\
|
\
|
||||||
while ((pcmFramesRead = (drflac_uint64)drflac_read_pcm_frames_##extension(pFlac, sizeof(buffer)/sizeof(buffer[0])/pFlac->channels, buffer)) > 0) { \
|
newSampleDataBufferSize = sampleDataBufferSize * 2; \
|
||||||
if (((totalPCMFrameCount + pcmFramesRead) * pFlac->channels * sizeof(type)) > sampleDataBufferSize) { \
|
pNewSampleData = (type*)drflac__realloc_from_callbacks(pSampleData, newSampleDataBufferSize, sampleDataBufferSize, &pFlac->allocationCallbacks); \
|
||||||
type* pNewSampleData; \
|
if (pNewSampleData == NULL) { \
|
||||||
size_t newSampleDataBufferSize; \
|
drflac__free_from_callbacks(pSampleData, &pFlac->allocationCallbacks); \
|
||||||
\
|
goto on_error; \
|
||||||
newSampleDataBufferSize = sampleDataBufferSize * 2; \
|
|
||||||
pNewSampleData = (type*)drflac__realloc_from_callbacks(pSampleData, newSampleDataBufferSize, sampleDataBufferSize, &pFlac->allocationCallbacks); \
|
|
||||||
if (pNewSampleData == NULL) { \
|
|
||||||
drflac__free_from_callbacks(pSampleData, &pFlac->allocationCallbacks); \
|
|
||||||
goto on_error; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
sampleDataBufferSize = newSampleDataBufferSize; \
|
|
||||||
pSampleData = pNewSampleData; \
|
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
DRFLAC_COPY_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), buffer, (size_t)(pcmFramesRead*pFlac->channels*sizeof(type))); \
|
sampleDataBufferSize = newSampleDataBufferSize; \
|
||||||
totalPCMFrameCount += pcmFramesRead; \
|
pSampleData = pNewSampleData; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* At this point everything should be decoded, but we just want to fill the unused part buffer with silence - need to \
|
DRFLAC_COPY_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), buffer, (size_t)(pcmFramesRead*pFlac->channels*sizeof(type))); \
|
||||||
protect those ears from random noise! */ \
|
totalPCMFrameCount += pcmFramesRead; \
|
||||||
DRFLAC_ZERO_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), (size_t)(sampleDataBufferSize - totalPCMFrameCount*pFlac->channels*sizeof(type))); \
|
|
||||||
} else { \
|
|
||||||
drflac_uint64 dataSize = totalPCMFrameCount*pFlac->channels*sizeof(type); \
|
|
||||||
if (dataSize > (drflac_uint64)DRFLAC_SIZE_MAX) { \
|
|
||||||
goto on_error; /* The decoded data is too big. */ \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
pSampleData = (type*)drflac__malloc_from_callbacks((size_t)dataSize, &pFlac->allocationCallbacks); /* <-- Safe cast as per the check above. */ \
|
|
||||||
if (pSampleData == NULL) { \
|
|
||||||
goto on_error; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
totalPCMFrameCount = drflac_read_pcm_frames_##extension(pFlac, pFlac->totalPCMFrameCount, pSampleData); \
|
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
|
/* At this point everything should be decoded, but we just want to fill the unused part buffer with silence - need to \
|
||||||
|
protect those ears from random noise! */ \
|
||||||
|
DRFLAC_ZERO_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), (size_t)(sampleDataBufferSize - totalPCMFrameCount*pFlac->channels*sizeof(type))); \
|
||||||
|
\
|
||||||
if (sampleRateOut) *sampleRateOut = pFlac->sampleRate; \
|
if (sampleRateOut) *sampleRateOut = pFlac->sampleRate; \
|
||||||
if (channelsOut) *channelsOut = pFlac->channels; \
|
if (channelsOut) *channelsOut = pFlac->channels; \
|
||||||
if (totalPCMFrameCountOut) *totalPCMFrameCountOut = totalPCMFrameCount; \
|
if (totalPCMFrameCountOut) *totalPCMFrameCountOut = totalPCMFrameCount; \
|
||||||
|
|
@ -12077,7 +12169,19 @@ DRFLAC_API drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterat
|
||||||
/*
|
/*
|
||||||
REVISION HISTORY
|
REVISION HISTORY
|
||||||
================
|
================
|
||||||
v0.13.0 - TBD
|
v0.13.3 - 2026-01-17
|
||||||
|
- Fix a compiler compatibility issue with some inlined assembly.
|
||||||
|
- Fix a compilation warning.
|
||||||
|
|
||||||
|
v0.13.2 - 2025-12-02
|
||||||
|
- Improve robustness of the parsing of picture metadata to improve support for memory constrained embedded devices.
|
||||||
|
- Fix a warning about an assigned by unused variable.
|
||||||
|
- Improvements to drflac_open_and_read_pcm_frames_*() and family to avoid excessively large memory allocations from malformed files.
|
||||||
|
|
||||||
|
v0.13.1 - 2025-09-10
|
||||||
|
- Fix an error with the NXDK build.
|
||||||
|
|
||||||
|
v0.13.0 - 2025-07-23
|
||||||
- API CHANGE: Seek origin enums have been renamed to match the naming convention used by other dr_libs libraries:
|
- API CHANGE: Seek origin enums have been renamed to match the naming convention used by other dr_libs libraries:
|
||||||
- drflac_seek_origin_start -> DRFLAC_SEEK_SET
|
- drflac_seek_origin_start -> DRFLAC_SEEK_SET
|
||||||
- drflac_seek_origin_current -> DRFLAC_SEEK_CUR
|
- drflac_seek_origin_current -> DRFLAC_SEEK_CUR
|
||||||
|
|
|
||||||
171
src/external/dr_mp3.h
vendored
171
src/external/dr_mp3.h
vendored
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
MP3 audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
|
MP3 audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
|
||||||
dr_mp3 - v0.7.0 - TBD
|
dr_mp3 - v0.7.4 - TBD
|
||||||
|
|
||||||
David Reid - mackron@gmail.com
|
David Reid - mackron@gmail.com
|
||||||
|
|
||||||
|
|
@ -72,7 +72,7 @@ extern "C" {
|
||||||
|
|
||||||
#define DRMP3_VERSION_MAJOR 0
|
#define DRMP3_VERSION_MAJOR 0
|
||||||
#define DRMP3_VERSION_MINOR 7
|
#define DRMP3_VERSION_MINOR 7
|
||||||
#define DRMP3_VERSION_REVISION 0
|
#define DRMP3_VERSION_REVISION 4
|
||||||
#define DRMP3_VERSION_STRING DRMP3_XSTRINGIFY(DRMP3_VERSION_MAJOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_MINOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_REVISION)
|
#define DRMP3_VERSION_STRING DRMP3_XSTRINGIFY(DRMP3_VERSION_MAJOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_MINOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_REVISION)
|
||||||
|
|
||||||
#include <stddef.h> /* For size_t. */
|
#include <stddef.h> /* For size_t. */
|
||||||
|
|
@ -257,16 +257,45 @@ typedef struct
|
||||||
Low Level Push API
|
Low Level Push API
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
|
#define DRMP3_MAX_BITRESERVOIR_BYTES 511
|
||||||
|
#define DRMP3_MAX_FREE_FORMAT_FRAME_SIZE 2304 /* more than ISO spec's */
|
||||||
|
#define DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES DRMP3_MAX_FREE_FORMAT_FRAME_SIZE /* MUST be >= 320000/8/32000*1152 = 1440 */
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int frame_bytes, channels, sample_rate, layer, bitrate_kbps;
|
int frame_bytes, channels, sample_rate, layer, bitrate_kbps;
|
||||||
} drmp3dec_frame_info;
|
} drmp3dec_frame_info;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const drmp3_uint8 *buf;
|
||||||
|
int pos, limit;
|
||||||
|
} drmp3_bs;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const drmp3_uint8 *sfbtab;
|
||||||
|
drmp3_uint16 part_23_length, big_values, scalefac_compress;
|
||||||
|
drmp3_uint8 global_gain, block_type, mixed_block_flag, n_long_sfb, n_short_sfb;
|
||||||
|
drmp3_uint8 table_select[3], region_count[3], subblock_gain[3];
|
||||||
|
drmp3_uint8 preflag, scalefac_scale, count1_table, scfsi;
|
||||||
|
} drmp3_L3_gr_info;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
drmp3_bs bs;
|
||||||
|
drmp3_uint8 maindata[DRMP3_MAX_BITRESERVOIR_BYTES + DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES];
|
||||||
|
drmp3_L3_gr_info gr_info[4];
|
||||||
|
float grbuf[2][576], scf[40], syn[18 + 15][2*32];
|
||||||
|
drmp3_uint8 ist_pos[2][39];
|
||||||
|
} drmp3dec_scratch;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
float mdct_overlap[2][9*32], qmf_state[15*2*32];
|
float mdct_overlap[2][9*32], qmf_state[15*2*32];
|
||||||
int reserv, free_format_bytes;
|
int reserv, free_format_bytes;
|
||||||
drmp3_uint8 header[4], reserv_buf[511];
|
drmp3_uint8 header[4], reserv_buf[511];
|
||||||
|
drmp3dec_scratch scratch;
|
||||||
} drmp3dec;
|
} drmp3dec;
|
||||||
|
|
||||||
/* Initializes a low level decoder. */
|
/* Initializes a low level decoder. */
|
||||||
|
|
@ -592,14 +621,10 @@ DRMP3_API const char* drmp3_version_string(void)
|
||||||
|
|
||||||
#define DRMP3_OFFSET_PTR(p, offset) ((void*)((drmp3_uint8*)(p) + (offset)))
|
#define DRMP3_OFFSET_PTR(p, offset) ((void*)((drmp3_uint8*)(p) + (offset)))
|
||||||
|
|
||||||
#define DRMP3_MAX_FREE_FORMAT_FRAME_SIZE 2304 /* more than ISO spec's */
|
|
||||||
#ifndef DRMP3_MAX_FRAME_SYNC_MATCHES
|
#ifndef DRMP3_MAX_FRAME_SYNC_MATCHES
|
||||||
#define DRMP3_MAX_FRAME_SYNC_MATCHES 10
|
#define DRMP3_MAX_FRAME_SYNC_MATCHES 10
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES DRMP3_MAX_FREE_FORMAT_FRAME_SIZE /* MUST be >= 320000/8/32000*1152 = 1440 */
|
|
||||||
|
|
||||||
#define DRMP3_MAX_BITRESERVOIR_BYTES 511
|
|
||||||
#define DRMP3_SHORT_BLOCK_TYPE 2
|
#define DRMP3_SHORT_BLOCK_TYPE 2
|
||||||
#define DRMP3_STOP_BLOCK_TYPE 3
|
#define DRMP3_STOP_BLOCK_TYPE 3
|
||||||
#define DRMP3_MODE_MONO 3
|
#define DRMP3_MODE_MONO 3
|
||||||
|
|
@ -632,8 +657,10 @@ DRMP3_API const char* drmp3_version_string(void)
|
||||||
|
|
||||||
#if !defined(DR_MP3_NO_SIMD)
|
#if !defined(DR_MP3_NO_SIMD)
|
||||||
|
|
||||||
#if !defined(DR_MP3_ONLY_SIMD) && (defined(_M_X64) || defined(__x86_64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC))
|
#if !defined(DR_MP3_ONLY_SIMD) && ((defined(_MSC_VER) && _MSC_VER >= 1400) && defined(_M_X64)) || ((defined(__i386) || defined(_M_IX86) || defined(__i386__) || defined(__x86_64__)) && ((defined(_M_IX86_FP) && _M_IX86_FP == 2) || defined(__SSE2__)))
|
||||||
/* x64 always have SSE2, arm64 always have neon, no need for generic code */
|
#define DR_MP3_ONLY_SIMD
|
||||||
|
#endif
|
||||||
|
#if !defined(DR_MP3_ONLY_SIMD) && (defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC))
|
||||||
#define DR_MP3_ONLY_SIMD
|
#define DR_MP3_ONLY_SIMD
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -655,7 +682,7 @@ DRMP3_API const char* drmp3_version_string(void)
|
||||||
#define DRMP3_VMUL_S(x, s) _mm_mul_ps(x, _mm_set1_ps(s))
|
#define DRMP3_VMUL_S(x, s) _mm_mul_ps(x, _mm_set1_ps(s))
|
||||||
#define DRMP3_VREV(x) _mm_shuffle_ps(x, x, _MM_SHUFFLE(0, 1, 2, 3))
|
#define DRMP3_VREV(x) _mm_shuffle_ps(x, x, _MM_SHUFFLE(0, 1, 2, 3))
|
||||||
typedef __m128 drmp3_f4;
|
typedef __m128 drmp3_f4;
|
||||||
#if defined(_MSC_VER) || defined(DR_MP3_ONLY_SIMD)
|
#if (defined(_MSC_VER) || defined(DR_MP3_ONLY_SIMD)) && !defined(__clang__)
|
||||||
#define drmp3_cpuid __cpuid
|
#define drmp3_cpuid __cpuid
|
||||||
#else
|
#else
|
||||||
static __inline__ __attribute__((always_inline)) void drmp3_cpuid(int CPUInfo[], const int InfoType)
|
static __inline__ __attribute__((always_inline)) void drmp3_cpuid(int CPUInfo[], const int InfoType)
|
||||||
|
|
@ -779,11 +806,7 @@ static __inline__ __attribute__((always_inline)) drmp3_int32 drmp3_clip_int16_ar
|
||||||
#define DRMP3_FREE(p) free((p))
|
#define DRMP3_FREE(p) free((p))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
const drmp3_uint8 *buf;
|
|
||||||
int pos, limit;
|
|
||||||
} drmp3_bs;
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
|
@ -796,24 +819,6 @@ typedef struct
|
||||||
drmp3_uint8 tab_offset, code_tab_width, band_count;
|
drmp3_uint8 tab_offset, code_tab_width, band_count;
|
||||||
} drmp3_L12_subband_alloc;
|
} drmp3_L12_subband_alloc;
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
const drmp3_uint8 *sfbtab;
|
|
||||||
drmp3_uint16 part_23_length, big_values, scalefac_compress;
|
|
||||||
drmp3_uint8 global_gain, block_type, mixed_block_flag, n_long_sfb, n_short_sfb;
|
|
||||||
drmp3_uint8 table_select[3], region_count[3], subblock_gain[3];
|
|
||||||
drmp3_uint8 preflag, scalefac_scale, count1_table, scfsi;
|
|
||||||
} drmp3_L3_gr_info;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
drmp3_bs bs;
|
|
||||||
drmp3_uint8 maindata[DRMP3_MAX_BITRESERVOIR_BYTES + DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES];
|
|
||||||
drmp3_L3_gr_info gr_info[4];
|
|
||||||
float grbuf[2][576], scf[40], syn[18 + 15][2*32];
|
|
||||||
drmp3_uint8 ist_pos[2][39];
|
|
||||||
} drmp3dec_scratch;
|
|
||||||
|
|
||||||
static void drmp3_bs_init(drmp3_bs *bs, const drmp3_uint8 *data, int bytes)
|
static void drmp3_bs_init(drmp3_bs *bs, const drmp3_uint8 *data, int bytes)
|
||||||
{
|
{
|
||||||
bs->buf = data;
|
bs->buf = data;
|
||||||
|
|
@ -1227,6 +1232,14 @@ static float drmp3_L3_ldexp_q2(float y, int exp_q2)
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
I've had reports of GCC 14 throwing an incorrect -Wstringop-overflow warning here. This is an attempt
|
||||||
|
to silence this warning.
|
||||||
|
*/
|
||||||
|
#if (defined(__GNUC__) && (__GNUC__ >= 13)) && !defined(__clang__)
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wstringop-overflow"
|
||||||
|
#endif
|
||||||
static void drmp3_L3_decode_scalefactors(const drmp3_uint8 *hdr, drmp3_uint8 *ist_pos, drmp3_bs *bs, const drmp3_L3_gr_info *gr, float *scf, int ch)
|
static void drmp3_L3_decode_scalefactors(const drmp3_uint8 *hdr, drmp3_uint8 *ist_pos, drmp3_bs *bs, const drmp3_L3_gr_info *gr, float *scf, int ch)
|
||||||
{
|
{
|
||||||
static const drmp3_uint8 g_scf_partitions[3][28] = {
|
static const drmp3_uint8 g_scf_partitions[3][28] = {
|
||||||
|
|
@ -1288,6 +1301,9 @@ static void drmp3_L3_decode_scalefactors(const drmp3_uint8 *hdr, drmp3_uint8 *is
|
||||||
scf[i] = drmp3_L3_ldexp_q2(gain, iscf[i] << scf_shift);
|
scf[i] = drmp3_L3_ldexp_q2(gain, iscf[i] << scf_shift);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if (defined(__GNUC__) && (__GNUC__ >= 13)) && !defined(__clang__)
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
static const float g_drmp3_pow43[129 + 16] = {
|
static const float g_drmp3_pow43[129 + 16] = {
|
||||||
0,-1,-2.519842f,-4.326749f,-6.349604f,-8.549880f,-10.902724f,-13.390518f,-16.000000f,-18.720754f,-21.544347f,-24.463781f,-27.473142f,-30.567351f,-33.741992f,-36.993181f,
|
0,-1,-2.519842f,-4.326749f,-6.349604f,-8.549880f,-10.902724f,-13.390518f,-16.000000f,-18.720754f,-21.544347f,-24.463781f,-27.473142f,-30.567351f,-33.741992f,-36.993181f,
|
||||||
|
|
@ -2299,7 +2315,6 @@ DRMP3_API int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int m
|
||||||
int i = 0, igr, frame_size = 0, success = 1;
|
int i = 0, igr, frame_size = 0, success = 1;
|
||||||
const drmp3_uint8 *hdr;
|
const drmp3_uint8 *hdr;
|
||||||
drmp3_bs bs_frame[1];
|
drmp3_bs bs_frame[1];
|
||||||
drmp3dec_scratch scratch;
|
|
||||||
|
|
||||||
if (mp3_bytes > 4 && dec->header[0] == 0xff && drmp3_hdr_compare(dec->header, mp3))
|
if (mp3_bytes > 4 && dec->header[0] == 0xff && drmp3_hdr_compare(dec->header, mp3))
|
||||||
{
|
{
|
||||||
|
|
@ -2336,23 +2351,23 @@ DRMP3_API int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int m
|
||||||
|
|
||||||
if (info->layer == 3)
|
if (info->layer == 3)
|
||||||
{
|
{
|
||||||
int main_data_begin = drmp3_L3_read_side_info(bs_frame, scratch.gr_info, hdr);
|
int main_data_begin = drmp3_L3_read_side_info(bs_frame, dec->scratch.gr_info, hdr);
|
||||||
if (main_data_begin < 0 || bs_frame->pos > bs_frame->limit)
|
if (main_data_begin < 0 || bs_frame->pos > bs_frame->limit)
|
||||||
{
|
{
|
||||||
drmp3dec_init(dec);
|
drmp3dec_init(dec);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
success = drmp3_L3_restore_reservoir(dec, bs_frame, &scratch, main_data_begin);
|
success = drmp3_L3_restore_reservoir(dec, bs_frame, &dec->scratch, main_data_begin);
|
||||||
if (success && pcm != NULL)
|
if (success && pcm != NULL)
|
||||||
{
|
{
|
||||||
for (igr = 0; igr < (DRMP3_HDR_TEST_MPEG1(hdr) ? 2 : 1); igr++, pcm = DRMP3_OFFSET_PTR(pcm, sizeof(drmp3d_sample_t)*576*info->channels))
|
for (igr = 0; igr < (DRMP3_HDR_TEST_MPEG1(hdr) ? 2 : 1); igr++, pcm = DRMP3_OFFSET_PTR(pcm, sizeof(drmp3d_sample_t)*576*info->channels))
|
||||||
{
|
{
|
||||||
DRMP3_ZERO_MEMORY(scratch.grbuf[0], 576*2*sizeof(float));
|
DRMP3_ZERO_MEMORY(dec->scratch.grbuf[0], 576*2*sizeof(float));
|
||||||
drmp3_L3_decode(dec, &scratch, scratch.gr_info + igr*info->channels, info->channels);
|
drmp3_L3_decode(dec, &dec->scratch, dec->scratch.gr_info + igr*info->channels, info->channels);
|
||||||
drmp3d_synth_granule(dec->qmf_state, scratch.grbuf[0], 18, info->channels, (drmp3d_sample_t*)pcm, scratch.syn[0]);
|
drmp3d_synth_granule(dec->qmf_state, dec->scratch.grbuf[0], 18, info->channels, (drmp3d_sample_t*)pcm, dec->scratch.syn[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
drmp3_L3_save_reservoir(dec, &scratch);
|
drmp3_L3_save_reservoir(dec, &dec->scratch);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
#ifdef DR_MP3_ONLY_MP3
|
#ifdef DR_MP3_ONLY_MP3
|
||||||
|
|
@ -2366,15 +2381,15 @@ DRMP3_API int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int m
|
||||||
|
|
||||||
drmp3_L12_read_scale_info(hdr, bs_frame, sci);
|
drmp3_L12_read_scale_info(hdr, bs_frame, sci);
|
||||||
|
|
||||||
DRMP3_ZERO_MEMORY(scratch.grbuf[0], 576*2*sizeof(float));
|
DRMP3_ZERO_MEMORY(dec->scratch.grbuf[0], 576*2*sizeof(float));
|
||||||
for (i = 0, igr = 0; igr < 3; igr++)
|
for (i = 0, igr = 0; igr < 3; igr++)
|
||||||
{
|
{
|
||||||
if (12 == (i += drmp3_L12_dequantize_granule(scratch.grbuf[0] + i, bs_frame, sci, info->layer | 1)))
|
if (12 == (i += drmp3_L12_dequantize_granule(dec->scratch.grbuf[0] + i, bs_frame, sci, info->layer | 1)))
|
||||||
{
|
{
|
||||||
i = 0;
|
i = 0;
|
||||||
drmp3_L12_apply_scf_384(sci, sci->scf + igr, scratch.grbuf[0]);
|
drmp3_L12_apply_scf_384(sci, sci->scf + igr, dec->scratch.grbuf[0]);
|
||||||
drmp3d_synth_granule(dec->qmf_state, scratch.grbuf[0], 12, info->channels, (drmp3d_sample_t*)pcm, scratch.syn[0]);
|
drmp3d_synth_granule(dec->qmf_state, dec->scratch.grbuf[0], 12, info->channels, (drmp3d_sample_t*)pcm, dec->scratch.syn[0]);
|
||||||
DRMP3_ZERO_MEMORY(scratch.grbuf[0], 576*2*sizeof(float));
|
DRMP3_ZERO_MEMORY(dec->scratch.grbuf[0], 576*2*sizeof(float));
|
||||||
pcm = DRMP3_OFFSET_PTR(pcm, sizeof(drmp3d_sample_t)*384*info->channels);
|
pcm = DRMP3_OFFSET_PTR(pcm, sizeof(drmp3d_sample_t)*384*info->channels);
|
||||||
}
|
}
|
||||||
if (bs_frame->pos > bs_frame->limit)
|
if (bs_frame->pos > bs_frame->limit)
|
||||||
|
|
@ -3005,23 +3020,27 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
|
||||||
((drmp3_uint32)ape[26] << 16) |
|
((drmp3_uint32)ape[26] << 16) |
|
||||||
((drmp3_uint32)ape[27] << 24);
|
((drmp3_uint32)ape[27] << 24);
|
||||||
|
|
||||||
streamEndOffset -= 32 + tagSize;
|
if (32 + tagSize < streamLen) {
|
||||||
streamLen -= 32 + tagSize;
|
streamEndOffset -= 32 + tagSize;
|
||||||
|
streamLen -= 32 + tagSize;
|
||||||
/* Fire a metadata callback for the APE data. Must include both the main content and footer. */
|
|
||||||
if (onMeta != NULL) {
|
/* Fire a metadata callback for the APE data. Must include both the main content and footer. */
|
||||||
/* We first need to seek to the start of the APE tag. */
|
if (onMeta != NULL) {
|
||||||
if (onSeek(pUserData, streamEndOffset, DRMP3_SEEK_END)) {
|
/* We first need to seek to the start of the APE tag. */
|
||||||
size_t apeTagSize = (size_t)tagSize + 32;
|
if (onSeek(pUserData, streamEndOffset, DRMP3_SEEK_END)) {
|
||||||
drmp3_uint8* pTagData = (drmp3_uint8*)drmp3_malloc(apeTagSize, pAllocationCallbacks);
|
size_t apeTagSize = (size_t)tagSize + 32;
|
||||||
if (pTagData != NULL) {
|
drmp3_uint8* pTagData = (drmp3_uint8*)drmp3_malloc(apeTagSize, pAllocationCallbacks);
|
||||||
if (onRead(pUserData, pTagData, apeTagSize) == apeTagSize) {
|
if (pTagData != NULL) {
|
||||||
drmp3__on_meta(pMP3, DRMP3_METADATA_TYPE_APE, pTagData, apeTagSize);
|
if (onRead(pUserData, pTagData, apeTagSize) == apeTagSize) {
|
||||||
}
|
drmp3__on_meta(pMP3, DRMP3_METADATA_TYPE_APE, pTagData, apeTagSize);
|
||||||
|
}
|
||||||
|
|
||||||
drmp3_free(pTagData, pAllocationCallbacks);
|
drmp3_free(pTagData, pAllocationCallbacks);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
/* The tag size is larger than the stream. Invalid APE tag. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3153,7 +3172,6 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
|
||||||
{
|
{
|
||||||
drmp3_bs bs;
|
drmp3_bs bs;
|
||||||
drmp3_L3_gr_info grInfo[4];
|
drmp3_L3_gr_info grInfo[4];
|
||||||
const drmp3_uint8* pTagData = pFirstFrameData;
|
|
||||||
|
|
||||||
drmp3_bs_init(&bs, pFirstFrameData + DRMP3_HDR_SIZE, firstFrameInfo.frame_bytes - DRMP3_HDR_SIZE);
|
drmp3_bs_init(&bs, pFirstFrameData + DRMP3_HDR_SIZE, firstFrameInfo.frame_bytes - DRMP3_HDR_SIZE);
|
||||||
|
|
||||||
|
|
@ -3164,6 +3182,7 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
|
||||||
if (drmp3_L3_read_side_info(&bs, grInfo, pFirstFrameData) >= 0) {
|
if (drmp3_L3_read_side_info(&bs, grInfo, pFirstFrameData) >= 0) {
|
||||||
drmp3_bool32 isXing = DRMP3_FALSE;
|
drmp3_bool32 isXing = DRMP3_FALSE;
|
||||||
drmp3_bool32 isInfo = DRMP3_FALSE;
|
drmp3_bool32 isInfo = DRMP3_FALSE;
|
||||||
|
const drmp3_uint8* pTagData;
|
||||||
const drmp3_uint8* pTagDataBeg;
|
const drmp3_uint8* pTagDataBeg;
|
||||||
|
|
||||||
pTagDataBeg = pFirstFrameData + DRMP3_HDR_SIZE + (bs.pos/8);
|
pTagDataBeg = pFirstFrameData + DRMP3_HDR_SIZE + (bs.pos/8);
|
||||||
|
|
@ -3246,6 +3265,13 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
|
||||||
/* The start offset needs to be moved to the end of this frame so it's not included in any audio processing after seeking. */
|
/* The start offset needs to be moved to the end of this frame so it's not included in any audio processing after seeking. */
|
||||||
pMP3->streamStartOffset += (drmp3_uint32)(firstFrameInfo.frame_bytes);
|
pMP3->streamStartOffset += (drmp3_uint32)(firstFrameInfo.frame_bytes);
|
||||||
pMP3->streamCursor = pMP3->streamStartOffset;
|
pMP3->streamCursor = pMP3->streamStartOffset;
|
||||||
|
|
||||||
|
/*
|
||||||
|
The internal decoder needs to be reset to clear out any state. If we don't reset this state, it's possible for
|
||||||
|
there to be inconsistencies in the number of samples read when reading to the end of the stream depending on
|
||||||
|
whether or not the caller seeks to the start of the stream.
|
||||||
|
*/
|
||||||
|
drmp3dec_init(&pMP3->decoder);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Failed to read the side info. */
|
/* Failed to read the side info. */
|
||||||
|
|
@ -3307,8 +3333,6 @@ static drmp3_bool32 drmp3__on_seek_memory(void* pUserData, int byteOffset, drmp3
|
||||||
|
|
||||||
DRMP3_ASSERT(pMP3 != NULL);
|
DRMP3_ASSERT(pMP3 != NULL);
|
||||||
|
|
||||||
newCursor = pMP3->memory.currentReadPos;
|
|
||||||
|
|
||||||
if (origin == DRMP3_SEEK_SET) {
|
if (origin == DRMP3_SEEK_SET) {
|
||||||
newCursor = 0;
|
newCursor = 0;
|
||||||
} else if (origin == DRMP3_SEEK_CUR) {
|
} else if (origin == DRMP3_SEEK_CUR) {
|
||||||
|
|
@ -3981,7 +4005,7 @@ static drmp3_bool32 drmp3__on_tell_stdio(void* pUserData, drmp3_int64* pCursor)
|
||||||
DRMP3_ASSERT(pFileStdio != NULL);
|
DRMP3_ASSERT(pFileStdio != NULL);
|
||||||
DRMP3_ASSERT(pCursor != NULL);
|
DRMP3_ASSERT(pCursor != NULL);
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32) && !defined(NXDK)
|
||||||
#if defined(_MSC_VER) && _MSC_VER > 1200
|
#if defined(_MSC_VER) && _MSC_VER > 1200
|
||||||
result = _ftelli64(pFileStdio);
|
result = _ftelli64(pFileStdio);
|
||||||
#else
|
#else
|
||||||
|
|
@ -4780,6 +4804,8 @@ static float* drmp3__full_read_and_close_f32(drmp3* pMP3, drmp3_config* pConfig,
|
||||||
pNewFrames = (float*)drmp3__realloc_from_callbacks(pFrames, (size_t)newFramesBufferSize, (size_t)oldFramesBufferSize, &pMP3->allocationCallbacks);
|
pNewFrames = (float*)drmp3__realloc_from_callbacks(pFrames, (size_t)newFramesBufferSize, (size_t)oldFramesBufferSize, &pMP3->allocationCallbacks);
|
||||||
if (pNewFrames == NULL) {
|
if (pNewFrames == NULL) {
|
||||||
drmp3__free_from_callbacks(pFrames, &pMP3->allocationCallbacks);
|
drmp3__free_from_callbacks(pFrames, &pMP3->allocationCallbacks);
|
||||||
|
pFrames = NULL;
|
||||||
|
totalFramesRead = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4847,6 +4873,8 @@ static drmp3_int16* drmp3__full_read_and_close_s16(drmp3* pMP3, drmp3_config* pC
|
||||||
pNewFrames = (drmp3_int16*)drmp3__realloc_from_callbacks(pFrames, (size_t)newFramesBufferSize, (size_t)oldFramesBufferSize, &pMP3->allocationCallbacks);
|
pNewFrames = (drmp3_int16*)drmp3__realloc_from_callbacks(pFrames, (size_t)newFramesBufferSize, (size_t)oldFramesBufferSize, &pMP3->allocationCallbacks);
|
||||||
if (pNewFrames == NULL) {
|
if (pNewFrames == NULL) {
|
||||||
drmp3__free_from_callbacks(pFrames, &pMP3->allocationCallbacks);
|
drmp3__free_from_callbacks(pFrames, &pMP3->allocationCallbacks);
|
||||||
|
pFrames = NULL;
|
||||||
|
totalFramesRead = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4981,7 +5009,24 @@ DIFFERENCES BETWEEN minimp3 AND dr_mp3
|
||||||
/*
|
/*
|
||||||
REVISION HISTORY
|
REVISION HISTORY
|
||||||
================
|
================
|
||||||
v0.7.0 - TBD
|
v0.7.4 - TBD
|
||||||
|
- Improvements to SIMD detection.
|
||||||
|
|
||||||
|
v0.7.3 - 2026-01-17
|
||||||
|
- Fix an error in drmp3_open_and_read_pcm_frames_s16() and family when memory allocation fails.
|
||||||
|
- Fix some compilation warnings.
|
||||||
|
|
||||||
|
v0.7.2 - 2025-12-02
|
||||||
|
- Reduce stack space to improve robustness on embedded systems.
|
||||||
|
- Fix a compilation error with MSVC Clang toolset relating to cpuid.
|
||||||
|
- Fix an error with APE tag parsing.
|
||||||
|
|
||||||
|
v0.7.1 - 2025-09-10
|
||||||
|
- Silence a warning with GCC.
|
||||||
|
- Fix an error with the NXDK build.
|
||||||
|
- Fix a decoding inconsistency when seeking. Prior to this change, reading to the end of the stream immediately after initializing will result in a different number of samples read than if the stream is seeked to the start and read to the end.
|
||||||
|
|
||||||
|
v0.7.0 - 2025-07-23
|
||||||
- The old `DRMP3_IMPLEMENTATION` has been removed. Use `DR_MP3_IMPLEMENTATION` instead. The reason for this change is that in the future everything will eventually be using the underscored naming convention in the future, so `drmp3` will become `dr_mp3`.
|
- The old `DRMP3_IMPLEMENTATION` has been removed. Use `DR_MP3_IMPLEMENTATION` instead. The reason for this change is that in the future everything will eventually be using the underscored naming convention in the future, so `drmp3` will become `dr_mp3`.
|
||||||
- API CHANGE: Seek origins have been renamed to match the naming convention used by dr_wav and my other libraries.
|
- API CHANGE: Seek origins have been renamed to match the naming convention used by dr_wav and my other libraries.
|
||||||
- drmp3_seek_origin_start -> DRMP3_SEEK_SET
|
- drmp3_seek_origin_start -> DRMP3_SEEK_SET
|
||||||
|
|
|
||||||
133
src/external/dr_wav.h
vendored
133
src/external/dr_wav.h
vendored
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
WAV audio loader and writer. Choice of public domain or MIT-0. See license statements at the end of this file.
|
WAV audio loader and writer. Choice of public domain or MIT-0. See license statements at the end of this file.
|
||||||
dr_wav - v0.14.0 - TBD
|
dr_wav - v0.14.5 - 2026-03-03
|
||||||
|
|
||||||
David Reid - mackron@gmail.com
|
David Reid - mackron@gmail.com
|
||||||
|
|
||||||
|
|
@ -147,7 +147,7 @@ extern "C" {
|
||||||
|
|
||||||
#define DRWAV_VERSION_MAJOR 0
|
#define DRWAV_VERSION_MAJOR 0
|
||||||
#define DRWAV_VERSION_MINOR 14
|
#define DRWAV_VERSION_MINOR 14
|
||||||
#define DRWAV_VERSION_REVISION 0
|
#define DRWAV_VERSION_REVISION 5
|
||||||
#define DRWAV_VERSION_STRING DRWAV_XSTRINGIFY(DRWAV_VERSION_MAJOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_MINOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_REVISION)
|
#define DRWAV_VERSION_STRING DRWAV_XSTRINGIFY(DRWAV_VERSION_MAJOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_MINOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_REVISION)
|
||||||
|
|
||||||
#include <stddef.h> /* For size_t. */
|
#include <stddef.h> /* For size_t. */
|
||||||
|
|
@ -2189,6 +2189,22 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_pars
|
||||||
|
|
||||||
if (pMetadata != NULL && bytesJustRead == sizeof(smplHeaderData)) {
|
if (pMetadata != NULL && bytesJustRead == sizeof(smplHeaderData)) {
|
||||||
drwav_uint32 iSampleLoop;
|
drwav_uint32 iSampleLoop;
|
||||||
|
drwav_uint32 loopCount;
|
||||||
|
drwav_uint32 calculatedLoopCount;
|
||||||
|
|
||||||
|
/*
|
||||||
|
When we calcualted the amount of memory required for the "smpl" chunk we excluded the chunk entirely
|
||||||
|
if the loop count in the header did not match with the calculated count based on the size of the
|
||||||
|
chunk. When this happens, the second stage will still hit this path but the `pMetadata` will be
|
||||||
|
non-null, but will either be pointing at the very end of the allocation or at the start of another
|
||||||
|
chunk. We need to check the loop counts for consistency *before* dereferencing the pMetadata object
|
||||||
|
so it's consistent with how we do it in the first stage.
|
||||||
|
*/
|
||||||
|
loopCount = drwav_bytes_to_u32(smplHeaderData + 28);
|
||||||
|
calculatedLoopCount = (pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES;
|
||||||
|
if (loopCount != calculatedLoopCount) {
|
||||||
|
return totalBytesRead;
|
||||||
|
}
|
||||||
|
|
||||||
pMetadata->type = drwav_metadata_type_smpl;
|
pMetadata->type = drwav_metadata_type_smpl;
|
||||||
pMetadata->data.smpl.manufacturerId = drwav_bytes_to_u32(smplHeaderData + 0);
|
pMetadata->data.smpl.manufacturerId = drwav_bytes_to_u32(smplHeaderData + 0);
|
||||||
|
|
@ -2205,7 +2221,7 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_pars
|
||||||
The loop count needs to be validated against the size of the chunk for safety so we don't
|
The loop count needs to be validated against the size of the chunk for safety so we don't
|
||||||
attempt to read over the boundary of the chunk.
|
attempt to read over the boundary of the chunk.
|
||||||
*/
|
*/
|
||||||
if (pMetadata->data.smpl.sampleLoopCount == (pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES) {
|
if (pMetadata->data.smpl.sampleLoopCount == calculatedLoopCount) {
|
||||||
pMetadata->data.smpl.pLoops = (drwav_smpl_loop*)drwav__metadata_get_memory(pParser, sizeof(drwav_smpl_loop) * pMetadata->data.smpl.sampleLoopCount, DRWAV_METADATA_ALIGNMENT);
|
pMetadata->data.smpl.pLoops = (drwav_smpl_loop*)drwav__metadata_get_memory(pParser, sizeof(drwav_smpl_loop) * pMetadata->data.smpl.sampleLoopCount, DRWAV_METADATA_ALIGNMENT);
|
||||||
|
|
||||||
for (iSampleLoop = 0; iSampleLoop < pMetadata->data.smpl.sampleLoopCount; ++iSampleLoop) {
|
for (iSampleLoop = 0; iSampleLoop < pMetadata->data.smpl.sampleLoopCount; ++iSampleLoop) {
|
||||||
|
|
@ -2230,6 +2246,15 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_pars
|
||||||
|
|
||||||
drwav__metadata_parser_read(pParser, pMetadata->data.smpl.pSamplerSpecificData, pMetadata->data.smpl.samplerSpecificDataSizeInBytes, &totalBytesRead);
|
drwav__metadata_parser_read(pParser, pMetadata->data.smpl.pSamplerSpecificData, pMetadata->data.smpl.samplerSpecificDataSizeInBytes, &totalBytesRead);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
Getting here means the loop count in the header does not match up with the size of the
|
||||||
|
chunk. Clear out the data to zero just to be safe.
|
||||||
|
|
||||||
|
This should never actually get hit because we check for it above, but keeping this here
|
||||||
|
for added safety.
|
||||||
|
*/
|
||||||
|
DRWAV_ZERO_OBJECT(&pMetadata->data.smpl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3605,7 +3630,7 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on
|
||||||
we'll need to abort because we can't be doing a backwards seek back to the SSND chunk in order to read the
|
we'll need to abort because we can't be doing a backwards seek back to the SSND chunk in order to read the
|
||||||
data. For this reason, this configuration of AIFF files are not supported with sequential mode.
|
data. For this reason, this configuration of AIFF files are not supported with sequential mode.
|
||||||
*/
|
*/
|
||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
chunkSize += header.paddingSize; /* <-- Make sure we seek past the padding. */
|
chunkSize += header.paddingSize; /* <-- Make sure we seek past the padding. */
|
||||||
|
|
@ -5285,7 +5310,7 @@ DRWAV_PRIVATE drwav_bool32 drwav__on_tell_stdio(void* pUserData, drwav_int64* pC
|
||||||
DRWAV_ASSERT(pFileStdio != NULL);
|
DRWAV_ASSERT(pFileStdio != NULL);
|
||||||
DRWAV_ASSERT(pCursor != NULL);
|
DRWAV_ASSERT(pCursor != NULL);
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32) && !defined(NXDK)
|
||||||
#if defined(_MSC_VER) && _MSC_VER > 1200
|
#if defined(_MSC_VER) && _MSC_VER > 1200
|
||||||
result = _ftelli64(pFileStdio);
|
result = _ftelli64(pFileStdio);
|
||||||
#else
|
#else
|
||||||
|
|
@ -5492,8 +5517,6 @@ DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory(void* pUserData, int offset, dr
|
||||||
|
|
||||||
DRWAV_ASSERT(pWav != NULL);
|
DRWAV_ASSERT(pWav != NULL);
|
||||||
|
|
||||||
newCursor = pWav->memoryStream.currentReadPos;
|
|
||||||
|
|
||||||
if (origin == DRWAV_SEEK_SET) {
|
if (origin == DRWAV_SEEK_SET) {
|
||||||
newCursor = 0;
|
newCursor = 0;
|
||||||
} else if (origin == DRWAV_SEEK_CUR) {
|
} else if (origin == DRWAV_SEEK_CUR) {
|
||||||
|
|
@ -5566,8 +5589,6 @@ DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory_write(void* pUserData, int offs
|
||||||
|
|
||||||
DRWAV_ASSERT(pWav != NULL);
|
DRWAV_ASSERT(pWav != NULL);
|
||||||
|
|
||||||
newCursor = pWav->memoryStreamWrite.currentWritePos;
|
|
||||||
|
|
||||||
if (origin == DRWAV_SEEK_SET) {
|
if (origin == DRWAV_SEEK_SET) {
|
||||||
newCursor = 0;
|
newCursor = 0;
|
||||||
} else if (origin == DRWAV_SEEK_CUR) {
|
} else if (origin == DRWAV_SEEK_CUR) {
|
||||||
|
|
@ -5576,7 +5597,7 @@ DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory_write(void* pUserData, int offs
|
||||||
newCursor = (drwav_int64)pWav->memoryStreamWrite.dataSize;
|
newCursor = (drwav_int64)pWav->memoryStreamWrite.dataSize;
|
||||||
} else {
|
} else {
|
||||||
DRWAV_ASSERT(!"Invalid seek origin");
|
DRWAV_ASSERT(!"Invalid seek origin");
|
||||||
return DRWAV_INVALID_ARGS;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
newCursor += offset;
|
newCursor += offset;
|
||||||
|
|
@ -6258,12 +6279,12 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
||||||
{
|
{
|
||||||
drwav_uint64 totalFramesRead = 0;
|
drwav_uint64 totalFramesRead = 0;
|
||||||
|
|
||||||
static drwav_int32 adaptationTable[] = {
|
static const drwav_int32 adaptationTable[] = {
|
||||||
230, 230, 230, 230, 307, 409, 512, 614,
|
230, 230, 230, 230, 307, 409, 512, 614,
|
||||||
768, 614, 512, 409, 307, 230, 230, 230
|
768, 614, 512, 409, 307, 230, 230, 230
|
||||||
};
|
};
|
||||||
static drwav_int32 coeff1Table[] = { 256, 512, 0, 192, 240, 460, 392 };
|
static const drwav_int32 coeff1Table[] = { 256, 512, 0, 192, 240, 460, 392 };
|
||||||
static drwav_int32 coeff2Table[] = { 0, -256, 0, 64, 0, -208, -232 };
|
static const drwav_int32 coeff2Table[] = { 0, -256, 0, 64, 0, -208, -232 };
|
||||||
|
|
||||||
DRWAV_ASSERT(pWav != NULL);
|
DRWAV_ASSERT(pWav != NULL);
|
||||||
DRWAV_ASSERT(framesToRead > 0);
|
DRWAV_ASSERT(framesToRead > 0);
|
||||||
|
|
@ -6292,7 +6313,7 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
||||||
pWav->msadpcm.cachedFrameCount = 2;
|
pWav->msadpcm.cachedFrameCount = 2;
|
||||||
|
|
||||||
/* The predictor is used as an index into coeff1Table so we'll need to validate to ensure it never overflows. */
|
/* The predictor is used as an index into coeff1Table so we'll need to validate to ensure it never overflows. */
|
||||||
if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table)) {
|
if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[0] >= drwav_countof(coeff2Table)) {
|
||||||
return totalFramesRead; /* Invalid file. */
|
return totalFramesRead; /* Invalid file. */
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -6319,7 +6340,8 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
||||||
pWav->msadpcm.cachedFrameCount = 2;
|
pWav->msadpcm.cachedFrameCount = 2;
|
||||||
|
|
||||||
/* The predictor is used as an index into coeff1Table so we'll need to validate to ensure it never overflows. */
|
/* The predictor is used as an index into coeff1Table so we'll need to validate to ensure it never overflows. */
|
||||||
if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[1] >= drwav_countof(coeff2Table)) {
|
if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[0] >= drwav_countof(coeff2Table) ||
|
||||||
|
pWav->msadpcm.predictor[1] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[1] >= drwav_countof(coeff2Table)) {
|
||||||
return totalFramesRead; /* Invalid file. */
|
return totalFramesRead; /* Invalid file. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -6373,15 +6395,17 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
||||||
drwav_int32 newSample0;
|
drwav_int32 newSample0;
|
||||||
drwav_int32 newSample1;
|
drwav_int32 newSample1;
|
||||||
|
|
||||||
|
/* The predictor is read from the file and then indexed into a table. Check that it's in bounds. */
|
||||||
|
if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[0] >= drwav_countof(coeff2Table)) {
|
||||||
|
return totalFramesRead;
|
||||||
|
}
|
||||||
|
|
||||||
newSample0 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
|
newSample0 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
|
||||||
newSample0 += nibble0 * pWav->msadpcm.delta[0];
|
newSample0 += nibble0 * pWav->msadpcm.delta[0];
|
||||||
newSample0 = drwav_clamp(newSample0, -32768, 32767);
|
newSample0 = drwav_clamp(newSample0, -32768, 32767);
|
||||||
|
|
||||||
pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8;
|
pWav->msadpcm.delta[0] = (drwav_int32)drwav_clamp(((drwav_int64)adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8, 16, 0x7FFFFFFF);
|
||||||
if (pWav->msadpcm.delta[0] < 16) {
|
|
||||||
pWav->msadpcm.delta[0] = 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
|
pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
|
||||||
pWav->msadpcm.prevFrames[0][1] = newSample0;
|
pWav->msadpcm.prevFrames[0][1] = newSample0;
|
||||||
|
|
||||||
|
|
@ -6390,15 +6414,11 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
||||||
newSample1 += nibble1 * pWav->msadpcm.delta[0];
|
newSample1 += nibble1 * pWav->msadpcm.delta[0];
|
||||||
newSample1 = drwav_clamp(newSample1, -32768, 32767);
|
newSample1 = drwav_clamp(newSample1, -32768, 32767);
|
||||||
|
|
||||||
pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[0]) >> 8;
|
pWav->msadpcm.delta[0] = (drwav_int32)drwav_clamp(((drwav_int64)adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[0]) >> 8, 16, 0x7FFFFFFF);
|
||||||
if (pWav->msadpcm.delta[0] < 16) {
|
|
||||||
pWav->msadpcm.delta[0] = 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
|
pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
|
||||||
pWav->msadpcm.prevFrames[0][1] = newSample1;
|
pWav->msadpcm.prevFrames[0][1] = newSample1;
|
||||||
|
|
||||||
|
|
||||||
pWav->msadpcm.cachedFrames[2] = newSample0;
|
pWav->msadpcm.cachedFrames[2] = newSample0;
|
||||||
pWav->msadpcm.cachedFrames[3] = newSample1;
|
pWav->msadpcm.cachedFrames[3] = newSample1;
|
||||||
pWav->msadpcm.cachedFrameCount = 2;
|
pWav->msadpcm.cachedFrameCount = 2;
|
||||||
|
|
@ -6408,28 +6428,30 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
||||||
drwav_int32 newSample1;
|
drwav_int32 newSample1;
|
||||||
|
|
||||||
/* Left. */
|
/* Left. */
|
||||||
|
if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[0] >= drwav_countof(coeff2Table)) {
|
||||||
|
return totalFramesRead; /* Out of bounds. Invalid file. */
|
||||||
|
}
|
||||||
|
|
||||||
newSample0 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
|
newSample0 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
|
||||||
newSample0 += nibble0 * pWav->msadpcm.delta[0];
|
newSample0 += nibble0 * pWav->msadpcm.delta[0];
|
||||||
newSample0 = drwav_clamp(newSample0, -32768, 32767);
|
newSample0 = drwav_clamp(newSample0, -32768, 32767);
|
||||||
|
|
||||||
pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8;
|
pWav->msadpcm.delta[0] = (drwav_int32)drwav_clamp(((drwav_int64)adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8, 16, 0x7FFFFFFF);
|
||||||
if (pWav->msadpcm.delta[0] < 16) {
|
|
||||||
pWav->msadpcm.delta[0] = 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
|
pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
|
||||||
pWav->msadpcm.prevFrames[0][1] = newSample0;
|
pWav->msadpcm.prevFrames[0][1] = newSample0;
|
||||||
|
|
||||||
|
|
||||||
/* Right. */
|
/* Right. */
|
||||||
|
if (pWav->msadpcm.predictor[1] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[1] >= drwav_countof(coeff2Table)) {
|
||||||
|
return totalFramesRead; /* Out of bounds. Invalid file. */
|
||||||
|
}
|
||||||
|
|
||||||
newSample1 = ((pWav->msadpcm.prevFrames[1][1] * coeff1Table[pWav->msadpcm.predictor[1]]) + (pWav->msadpcm.prevFrames[1][0] * coeff2Table[pWav->msadpcm.predictor[1]])) >> 8;
|
newSample1 = ((pWav->msadpcm.prevFrames[1][1] * coeff1Table[pWav->msadpcm.predictor[1]]) + (pWav->msadpcm.prevFrames[1][0] * coeff2Table[pWav->msadpcm.predictor[1]])) >> 8;
|
||||||
newSample1 += nibble1 * pWav->msadpcm.delta[1];
|
newSample1 += nibble1 * pWav->msadpcm.delta[1];
|
||||||
newSample1 = drwav_clamp(newSample1, -32768, 32767);
|
newSample1 = drwav_clamp(newSample1, -32768, 32767);
|
||||||
|
|
||||||
pWav->msadpcm.delta[1] = (adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[1]) >> 8;
|
pWav->msadpcm.delta[1] = (drwav_int32)drwav_clamp(((drwav_int64)adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[1]) >> 8, 16, 0x7FFFFFFF);
|
||||||
if (pWav->msadpcm.delta[1] < 16) {
|
|
||||||
pWav->msadpcm.delta[1] = 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
pWav->msadpcm.prevFrames[1][0] = pWav->msadpcm.prevFrames[1][1];
|
pWav->msadpcm.prevFrames[1][0] = pWav->msadpcm.prevFrames[1][1];
|
||||||
pWav->msadpcm.prevFrames[1][1] = newSample1;
|
pWav->msadpcm.prevFrames[1][1] = newSample1;
|
||||||
|
|
@ -6451,12 +6473,12 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ima(drwav* pWav, drwav_uin
|
||||||
drwav_uint64 totalFramesRead = 0;
|
drwav_uint64 totalFramesRead = 0;
|
||||||
drwav_uint32 iChannel;
|
drwav_uint32 iChannel;
|
||||||
|
|
||||||
static drwav_int32 indexTable[16] = {
|
static const drwav_int32 indexTable[16] = {
|
||||||
-1, -1, -1, -1, 2, 4, 6, 8,
|
-1, -1, -1, -1, 2, 4, 6, 8,
|
||||||
-1, -1, -1, -1, 2, 4, 6, 8
|
-1, -1, -1, -1, 2, 4, 6, 8
|
||||||
};
|
};
|
||||||
|
|
||||||
static drwav_int32 stepTable[89] = {
|
static const drwav_int32 stepTable[89] = {
|
||||||
7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
|
7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
|
||||||
19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
|
19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
|
||||||
50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
|
50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
|
||||||
|
|
@ -6606,7 +6628,7 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ima(drwav* pWav, drwav_uin
|
||||||
|
|
||||||
|
|
||||||
#ifndef DR_WAV_NO_CONVERSION_API
|
#ifndef DR_WAV_NO_CONVERSION_API
|
||||||
static unsigned short g_drwavAlawTable[256] = {
|
static const unsigned short g_drwavAlawTable[256] = {
|
||||||
0xEA80, 0xEB80, 0xE880, 0xE980, 0xEE80, 0xEF80, 0xEC80, 0xED80, 0xE280, 0xE380, 0xE080, 0xE180, 0xE680, 0xE780, 0xE480, 0xE580,
|
0xEA80, 0xEB80, 0xE880, 0xE980, 0xEE80, 0xEF80, 0xEC80, 0xED80, 0xE280, 0xE380, 0xE080, 0xE180, 0xE680, 0xE780, 0xE480, 0xE580,
|
||||||
0xF540, 0xF5C0, 0xF440, 0xF4C0, 0xF740, 0xF7C0, 0xF640, 0xF6C0, 0xF140, 0xF1C0, 0xF040, 0xF0C0, 0xF340, 0xF3C0, 0xF240, 0xF2C0,
|
0xF540, 0xF5C0, 0xF440, 0xF4C0, 0xF740, 0xF7C0, 0xF640, 0xF6C0, 0xF140, 0xF1C0, 0xF040, 0xF0C0, 0xF340, 0xF3C0, 0xF240, 0xF2C0,
|
||||||
0xAA00, 0xAE00, 0xA200, 0xA600, 0xBA00, 0xBE00, 0xB200, 0xB600, 0x8A00, 0x8E00, 0x8200, 0x8600, 0x9A00, 0x9E00, 0x9200, 0x9600,
|
0xAA00, 0xAE00, 0xA200, 0xA600, 0xBA00, 0xBE00, 0xB200, 0xB600, 0x8A00, 0x8E00, 0x8200, 0x8600, 0x9A00, 0x9E00, 0x9200, 0x9600,
|
||||||
|
|
@ -6625,7 +6647,7 @@ static unsigned short g_drwavAlawTable[256] = {
|
||||||
0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250, 0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350
|
0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250, 0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned short g_drwavMulawTable[256] = {
|
static const unsigned short g_drwavMulawTable[256] = {
|
||||||
0x8284, 0x8684, 0x8A84, 0x8E84, 0x9284, 0x9684, 0x9A84, 0x9E84, 0xA284, 0xA684, 0xAA84, 0xAE84, 0xB284, 0xB684, 0xBA84, 0xBE84,
|
0x8284, 0x8684, 0x8A84, 0x8E84, 0x9284, 0x9684, 0x9A84, 0x9E84, 0xA284, 0xA684, 0xAA84, 0xAE84, 0xB284, 0xB684, 0xBA84, 0xBE84,
|
||||||
0xC184, 0xC384, 0xC584, 0xC784, 0xC984, 0xCB84, 0xCD84, 0xCF84, 0xD184, 0xD384, 0xD584, 0xD784, 0xD984, 0xDB84, 0xDD84, 0xDF84,
|
0xC184, 0xC384, 0xC584, 0xC784, 0xC984, 0xCB84, 0xCD84, 0xCF84, 0xD184, 0xD384, 0xD584, 0xD784, 0xD984, 0xDB84, 0xDD84, 0xDF84,
|
||||||
0xE104, 0xE204, 0xE304, 0xE404, 0xE504, 0xE604, 0xE704, 0xE804, 0xE904, 0xEA04, 0xEB04, 0xEC04, 0xED04, 0xEE04, 0xEF04, 0xF004,
|
0xE104, 0xE204, 0xE304, 0xE404, 0xE504, 0xE604, 0xE704, 0xE804, 0xE904, 0xEA04, 0xEB04, 0xEC04, 0xED04, 0xEE04, 0xEF04, 0xF004,
|
||||||
|
|
@ -8053,6 +8075,12 @@ DRWAV_PRIVATE drwav_int16* drwav__read_pcm_frames_and_close_s16(drwav* pWav, uns
|
||||||
|
|
||||||
DRWAV_ASSERT(pWav != NULL);
|
DRWAV_ASSERT(pWav != NULL);
|
||||||
|
|
||||||
|
/* Check for overflow before multiplication. */
|
||||||
|
if (pWav->channels == 0 || pWav->totalPCMFrameCount > DRWAV_SIZE_MAX / pWav->channels / sizeof(drwav_int16)) {
|
||||||
|
drwav_uninit(pWav);
|
||||||
|
return NULL; /* Overflow or invalid channels. */
|
||||||
|
}
|
||||||
|
|
||||||
sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int16);
|
sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int16);
|
||||||
if (sampleDataSize > DRWAV_SIZE_MAX) {
|
if (sampleDataSize > DRWAV_SIZE_MAX) {
|
||||||
drwav_uninit(pWav);
|
drwav_uninit(pWav);
|
||||||
|
|
@ -8095,6 +8123,12 @@ DRWAV_PRIVATE float* drwav__read_pcm_frames_and_close_f32(drwav* pWav, unsigned
|
||||||
|
|
||||||
DRWAV_ASSERT(pWav != NULL);
|
DRWAV_ASSERT(pWav != NULL);
|
||||||
|
|
||||||
|
/* Check for overflow before multiplication. */
|
||||||
|
if (pWav->channels == 0 || pWav->totalPCMFrameCount > DRWAV_SIZE_MAX / pWav->channels / sizeof(float)) {
|
||||||
|
drwav_uninit(pWav);
|
||||||
|
return NULL; /* Overflow or invalid channels. */
|
||||||
|
}
|
||||||
|
|
||||||
sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(float);
|
sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(float);
|
||||||
if (sampleDataSize > DRWAV_SIZE_MAX) {
|
if (sampleDataSize > DRWAV_SIZE_MAX) {
|
||||||
drwav_uninit(pWav);
|
drwav_uninit(pWav);
|
||||||
|
|
@ -8137,6 +8171,12 @@ DRWAV_PRIVATE drwav_int32* drwav__read_pcm_frames_and_close_s32(drwav* pWav, uns
|
||||||
|
|
||||||
DRWAV_ASSERT(pWav != NULL);
|
DRWAV_ASSERT(pWav != NULL);
|
||||||
|
|
||||||
|
/* Check for overflow before multiplication. */
|
||||||
|
if (pWav->channels == 0 || pWav->totalPCMFrameCount > DRWAV_SIZE_MAX / pWav->channels / sizeof(drwav_int32)) {
|
||||||
|
drwav_uninit(pWav);
|
||||||
|
return NULL; /* Overflow or invalid channels. */
|
||||||
|
}
|
||||||
|
|
||||||
sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int32);
|
sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int32);
|
||||||
if (sampleDataSize > DRWAV_SIZE_MAX) {
|
if (sampleDataSize > DRWAV_SIZE_MAX) {
|
||||||
drwav_uninit(pWav);
|
drwav_uninit(pWav);
|
||||||
|
|
@ -8517,7 +8557,24 @@ DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b)
|
||||||
/*
|
/*
|
||||||
REVISION HISTORY
|
REVISION HISTORY
|
||||||
================
|
================
|
||||||
v0.14.0 - TBD
|
v0.14.5 - 2026-03-03
|
||||||
|
- Fix a crash when loading files with a malformed "smpl" chunk.
|
||||||
|
- Fix a signed overflow bug with the MS-ADPCM decoder.
|
||||||
|
|
||||||
|
v0.14.4 - 2026-01-17
|
||||||
|
- Fix some compilation warnings.
|
||||||
|
|
||||||
|
v0.14.3 - 2025-12-14
|
||||||
|
- Fix a possible out-of-bounds read when reading from MS-ADPCM encoded files.
|
||||||
|
- Fix a possible integer overflow error.
|
||||||
|
|
||||||
|
v0.14.2 - 2025-12-02
|
||||||
|
- Fix a compilation warning.
|
||||||
|
|
||||||
|
v0.14.1 - 2025-09-10
|
||||||
|
- Fix an error with the NXDK build.
|
||||||
|
|
||||||
|
v0.14.0 - 2025-07-23
|
||||||
- API CHANGE: Seek origin enums have been renamed to the following:
|
- API CHANGE: Seek origin enums have been renamed to the following:
|
||||||
- drwav_seek_origin_start -> DRWAV_SEEK_SET
|
- drwav_seek_origin_start -> DRWAV_SEEK_SET
|
||||||
- drwav_seek_origin_current -> DRWAV_SEEK_CUR
|
- drwav_seek_origin_current -> DRWAV_SEEK_CUR
|
||||||
|
|
|
||||||
53
src/external/m3d.h
vendored
53
src/external/m3d.h
vendored
|
|
@ -236,7 +236,8 @@ typedef struct {
|
||||||
#ifdef M3D_ASCII
|
#ifdef M3D_ASCII
|
||||||
#define M3D_PROPERTYDEF(f,i,n) { (f), (i), (char*)(n) }
|
#define M3D_PROPERTYDEF(f,i,n) { (f), (i), (char*)(n) }
|
||||||
char *key;
|
char *key;
|
||||||
#else
|
#endif
|
||||||
|
#ifndef M3D_ASCII
|
||||||
#define M3D_PROPERTYDEF(f,i,n) { (f), (i) }
|
#define M3D_PROPERTYDEF(f,i,n) { (f), (i) }
|
||||||
#endif
|
#endif
|
||||||
} m3dpd_t;
|
} m3dpd_t;
|
||||||
|
|
@ -414,7 +415,8 @@ typedef struct {
|
||||||
#ifdef M3D_ASCII
|
#ifdef M3D_ASCII
|
||||||
#define M3D_CMDDEF(t,n,p,a,b,c,d,e,f,g,h) { (char*)(n), (p), { (a), (b), (c), (d), (e), (f), (g), (h) } }
|
#define M3D_CMDDEF(t,n,p,a,b,c,d,e,f,g,h) { (char*)(n), (p), { (a), (b), (c), (d), (e), (f), (g), (h) } }
|
||||||
char *key;
|
char *key;
|
||||||
#else
|
#endif
|
||||||
|
#ifndef M3D_ASCII
|
||||||
#define M3D_CMDDEF(t,n,p,a,b,c,d,e,f,g,h) { (p), { (a), (b), (c), (d), (e), (f), (g), (h) } }
|
#define M3D_CMDDEF(t,n,p,a,b,c,d,e,f,g,h) { (p), { (a), (b), (c), (d), (e), (f), (g), (h) } }
|
||||||
#endif
|
#endif
|
||||||
uint8_t p;
|
uint8_t p;
|
||||||
|
|
@ -674,6 +676,10 @@ static m3dcd_t m3d_commandtypes[] = {
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
/* we'll need this with M3D_NOTEXTURE */
|
||||||
|
char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header);
|
||||||
|
|
||||||
|
#ifndef M3D_NOTEXTURE
|
||||||
#if !defined(M3D_NOIMPORTER) && !defined(STBI_INCLUDE_STB_IMAGE_H)
|
#if !defined(M3D_NOIMPORTER) && !defined(STBI_INCLUDE_STB_IMAGE_H)
|
||||||
/* PNG decompressor from
|
/* PNG decompressor from
|
||||||
|
|
||||||
|
|
@ -1868,6 +1874,11 @@ static void *_m3dstbi__png_load(_m3dstbi__context *s, int *x, int *y, int *comp,
|
||||||
#if !defined(M3D_NOIMPORTER) && defined(STBI_INCLUDE_STB_IMAGE_H) && !defined(STB_IMAGE_IMPLEMENTATION)
|
#if !defined(M3D_NOIMPORTER) && defined(STBI_INCLUDE_STB_IMAGE_H) && !defined(STB_IMAGE_IMPLEMENTATION)
|
||||||
#error "stb_image.h included without STB_IMAGE_IMPLEMENTATION. Sorry, we need some stuff defined inside the ifguard for proper integration"
|
#error "stb_image.h included without STB_IMAGE_IMPLEMENTATION. Sorry, we need some stuff defined inside the ifguard for proper integration"
|
||||||
#endif
|
#endif
|
||||||
|
#else
|
||||||
|
#if !defined(STBI_INCLUDE_STB_IMAGE_H) || defined(STBI_NO_ZLIB)
|
||||||
|
#error "stb_image.h not included or STBI_NO_ZLIB defined. Sorry, we need its zlib implementation for proper integration"
|
||||||
|
#endif
|
||||||
|
#endif /* M3D_NOTEXTURE */
|
||||||
|
|
||||||
#if defined(M3D_EXPORTER) && !defined(INCLUDE_STB_IMAGE_WRITE_H)
|
#if defined(M3D_EXPORTER) && !defined(INCLUDE_STB_IMAGE_WRITE_H)
|
||||||
/* zlib_compressor from
|
/* zlib_compressor from
|
||||||
|
|
@ -2168,9 +2179,11 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char
|
||||||
unsigned int i, len = 0;
|
unsigned int i, len = 0;
|
||||||
unsigned char *buff = NULL;
|
unsigned char *buff = NULL;
|
||||||
char *fn2;
|
char *fn2;
|
||||||
|
#ifndef M3D_NOTEXTURE
|
||||||
unsigned int w, h;
|
unsigned int w, h;
|
||||||
stbi__context s;
|
stbi__context s;
|
||||||
stbi__result_info ri;
|
stbi__result_info ri;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* failsafe */
|
/* failsafe */
|
||||||
if(!fn || !*fn) return M3D_UNDEF;
|
if(!fn || !*fn) return M3D_UNDEF;
|
||||||
|
|
@ -2209,13 +2222,17 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char
|
||||||
if(!model->texture) {
|
if(!model->texture) {
|
||||||
if(buff && freecb) (*freecb)(buff);
|
if(buff && freecb) (*freecb)(buff);
|
||||||
model->errcode = M3D_ERR_ALLOC;
|
model->errcode = M3D_ERR_ALLOC;
|
||||||
|
model->numtexture = 0;
|
||||||
return M3D_UNDEF;
|
return M3D_UNDEF;
|
||||||
}
|
}
|
||||||
|
memset(&model->texture[i], 0, sizeof(m3dtx_t));
|
||||||
model->texture[i].name = fn;
|
model->texture[i].name = fn;
|
||||||
model->texture[i].w = model->texture[i].h = 0; model->texture[i].d = NULL;
|
|
||||||
if(buff) {
|
if(buff) {
|
||||||
if(buff[0] == 0x89 && buff[1] == 'P' && buff[2] == 'N' && buff[3] == 'G') {
|
if(buff[0] == 0x89 && buff[1] == 'P' && buff[2] == 'N' && buff[3] == 'G') {
|
||||||
s.read_from_callbacks = 0;
|
#ifndef M3D_NOTEXTURE
|
||||||
|
/* return pixel buffer of the decoded texture */
|
||||||
|
memset(&s, 0, sizeof(s));
|
||||||
|
memset(&ri, 0, sizeof(ri));
|
||||||
s.img_buffer = s.img_buffer_original = (unsigned char *) buff;
|
s.img_buffer = s.img_buffer_original = (unsigned char *) buff;
|
||||||
s.img_buffer_end = s.img_buffer_original_end = (unsigned char *) buff+len;
|
s.img_buffer_end = s.img_buffer_original_end = (unsigned char *) buff+len;
|
||||||
/* don't use model->texture[i].w directly, it's a uint16_t */
|
/* don't use model->texture[i].w directly, it's a uint16_t */
|
||||||
|
|
@ -2225,6 +2242,16 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char
|
||||||
model->texture[i].w = w;
|
model->texture[i].w = w;
|
||||||
model->texture[i].h = h;
|
model->texture[i].h = h;
|
||||||
model->texture[i].f = (uint8_t)len;
|
model->texture[i].f = (uint8_t)len;
|
||||||
|
#else
|
||||||
|
/* return only the raw undecoded texture */
|
||||||
|
if((model->texture[i].d = (uint8_t*)M3D_MALLOC(len))) {
|
||||||
|
memcpy(model->texture[i].d, buff, len);
|
||||||
|
model->texture[i].w = len & 0xffff;
|
||||||
|
model->texture[i].h = (len >> 16) & 0xffff;
|
||||||
|
model->texture[i].f = 0;
|
||||||
|
} else
|
||||||
|
model->errcode = M3D_ERR_ALLOC;
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
#ifdef M3D_TX_INTERP
|
#ifdef M3D_TX_INTERP
|
||||||
if((model->errcode = M3D_TX_INTERP(fn, buff, len, &model->texture[i])) != M3D_SUCCESS) {
|
if((model->errcode = M3D_TX_INTERP(fn, buff, len, &model->texture[i])) != M3D_SUCCESS) {
|
||||||
|
|
@ -4280,7 +4307,7 @@ m3db_t *m3d_pose(m3d_t *model, M3D_INDEX actionid, uint32_t msec)
|
||||||
if(l != msec) {
|
if(l != msec) {
|
||||||
model->vertex = (m3dv_t*)M3D_REALLOC(model->vertex, (model->numvertex + 2 * model->numbone) * sizeof(m3dv_t));
|
model->vertex = (m3dv_t*)M3D_REALLOC(model->vertex, (model->numvertex + 2 * model->numbone) * sizeof(m3dv_t));
|
||||||
if(!model->vertex) {
|
if(!model->vertex) {
|
||||||
free(ret);
|
M3D_FREE(ret);
|
||||||
model->errcode = M3D_ERR_ALLOC;
|
model->errcode = M3D_ERR_ALLOC;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -4492,7 +4519,7 @@ void m3d_free(m3d_t *model)
|
||||||
if(model->label) M3D_FREE(model->label);
|
if(model->label) M3D_FREE(model->label);
|
||||||
if(model->inlined) M3D_FREE(model->inlined);
|
if(model->inlined) M3D_FREE(model->inlined);
|
||||||
if(model->extra) M3D_FREE(model->extra);
|
if(model->extra) M3D_FREE(model->extra);
|
||||||
free(model);
|
M3D_FREE(model);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -4568,15 +4595,15 @@ static uint32_t _m3d_stridx(m3dstr_t *str, uint32_t numstr, char *s)
|
||||||
safe = _m3d_safestr(s, 0);
|
safe = _m3d_safestr(s, 0);
|
||||||
if(!safe) return 0;
|
if(!safe) return 0;
|
||||||
if(!*safe) {
|
if(!*safe) {
|
||||||
free(safe);
|
M3D_FREE(safe);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
for(i = 0; i < numstr; i++)
|
for(i = 0; i < numstr; i++)
|
||||||
if(!strcmp(str[i].str, s)) {
|
if(!strcmp(str[i].str, s)) {
|
||||||
free(safe);
|
M3D_FREE(safe);
|
||||||
return str[i].offs;
|
return str[i].offs;
|
||||||
}
|
}
|
||||||
free(safe);
|
M3D_FREE(safe);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -4889,7 +4916,7 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
|
||||||
if(cmd->type == m3dc_mesh) {
|
if(cmd->type == m3dc_mesh) {
|
||||||
if(numgrp + 2 < maxgrp) {
|
if(numgrp + 2 < maxgrp) {
|
||||||
maxgrp += 1024;
|
maxgrp += 1024;
|
||||||
grpidx = (uint32_t*)realloc(grpidx, maxgrp * sizeof(uint32_t));
|
grpidx = (uint32_t*)M3D_REALLOC(grpidx, maxgrp * sizeof(uint32_t));
|
||||||
if(!grpidx) goto memerr;
|
if(!grpidx) goto memerr;
|
||||||
if(!numgrp) {
|
if(!numgrp) {
|
||||||
grpidx[0] = 0;
|
grpidx[0] = 0;
|
||||||
|
|
@ -5194,7 +5221,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
|
||||||
if(sa) M3D_FREE(sa);
|
if(sa) M3D_FREE(sa);
|
||||||
if(sd) M3D_FREE(sd);
|
if(sd) M3D_FREE(sd);
|
||||||
if(out) M3D_FREE(out);
|
if(out) M3D_FREE(out);
|
||||||
if(opa) free(opa);
|
if(opa) M3D_FREE(opa);
|
||||||
if(h) M3D_FREE(h);
|
if(h) M3D_FREE(h);
|
||||||
M3D_LOG("Out of memory");
|
M3D_LOG("Out of memory");
|
||||||
model->errcode = M3D_ERR_ALLOC;
|
model->errcode = M3D_ERR_ALLOC;
|
||||||
|
|
@ -6285,7 +6312,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
|
||||||
if(skin) M3D_FREE(skin);
|
if(skin) M3D_FREE(skin);
|
||||||
if(str) M3D_FREE(str);
|
if(str) M3D_FREE(str);
|
||||||
if(vrtx) M3D_FREE(vrtx);
|
if(vrtx) M3D_FREE(vrtx);
|
||||||
if(opa) free(opa);
|
if(opa) M3D_FREE(opa);
|
||||||
if(h) M3D_FREE(h);
|
if(h) M3D_FREE(h);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
@ -6310,7 +6337,7 @@ namespace M3D {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Model() {
|
Model() {
|
||||||
this->model = (m3d_t*)malloc(sizeof(m3d_t)); memset(this->model, 0, sizeof(m3d_t));
|
this->model = (m3d_t*)M3D_MALLOC(sizeof(m3d_t)); memset(this->model, 0, sizeof(m3d_t));
|
||||||
}
|
}
|
||||||
Model(_unused const std::string &data, _unused m3dread_t ReadFileCB,
|
Model(_unused const std::string &data, _unused m3dread_t ReadFileCB,
|
||||||
_unused m3dfree_t FreeCB, _unused M3D::Model mtllib) {
|
_unused m3dfree_t FreeCB, _unused M3D::Model mtllib) {
|
||||||
|
|
|
||||||
60
src/external/qoa.h
vendored
60
src/external/qoa.h
vendored
|
|
@ -31,7 +31,7 @@ struct {
|
||||||
struct {
|
struct {
|
||||||
char magic[4]; // magic bytes "qoaf"
|
char magic[4]; // magic bytes "qoaf"
|
||||||
uint32_t samples; // samples per channel in this file
|
uint32_t samples; // samples per channel in this file
|
||||||
} file_header;
|
} file_header;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -39,12 +39,12 @@ struct {
|
||||||
uint24_t samplerate; // samplerate in hz
|
uint24_t samplerate; // samplerate in hz
|
||||||
uint16_t fsamples; // samples per channel in this frame
|
uint16_t fsamples; // samples per channel in this frame
|
||||||
uint16_t fsize; // frame size (includes this header)
|
uint16_t fsize; // frame size (includes this header)
|
||||||
} frame_header;
|
} frame_header;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int16_t history[4]; // most recent last
|
int16_t history[4]; // most recent last
|
||||||
int16_t weights[4]; // most recent last
|
int16_t weights[4]; // most recent last
|
||||||
} lms_state[num_channels];
|
} lms_state[num_channels];
|
||||||
|
|
||||||
qoa_slice_t slices[256][num_channels];
|
qoa_slice_t slices[256][num_channels];
|
||||||
|
|
||||||
|
|
@ -66,7 +66,7 @@ frame may contain between 1 .. 256 (inclusive) slices per channel. The last
|
||||||
slice (for each channel) in the last frame may contain less than 20 samples; the
|
slice (for each channel) in the last frame may contain less than 20 samples; the
|
||||||
slice still must be 8 bytes wide, with the unused samples zeroed out.
|
slice still must be 8 bytes wide, with the unused samples zeroed out.
|
||||||
|
|
||||||
Channels are interleaved per slice. E.g. for 2 channel stereo:
|
Channels are interleaved per slice. E.g. for 2 channel stereo:
|
||||||
slice[0] = L, slice[1] = R, slice[2] = L, slice[3] = R ...
|
slice[0] = L, slice[1] = R, slice[2] = L, slice[3] = R ...
|
||||||
|
|
||||||
A valid QOA file or stream must have at least one frame. Each frame must contain
|
A valid QOA file or stream must have at least one frame. Each frame must contain
|
||||||
|
|
@ -74,7 +74,7 @@ at least one channel and one sample with a samplerate between 1 .. 16777215
|
||||||
(inclusive).
|
(inclusive).
|
||||||
|
|
||||||
If the total number of samples is not known by the encoder, the samples in the
|
If the total number of samples is not known by the encoder, the samples in the
|
||||||
file header may be set to 0x00000000 to indicate that the encoder is
|
file header may be set to 0x00000000 to indicate that the encoder is
|
||||||
"streaming". In a streaming context, the samplerate and number of channels may
|
"streaming". In a streaming context, the samplerate and number of channels may
|
||||||
differ from frame to frame. For static files (those with samples set to a
|
differ from frame to frame. For static files (those with samples set to a
|
||||||
non-zero value), each frame must have the same number of channels and same
|
non-zero value), each frame must have the same number of channels and same
|
||||||
|
|
@ -88,15 +88,15 @@ counts 1 .. 8 is:
|
||||||
|
|
||||||
1. Mono
|
1. Mono
|
||||||
2. L, R
|
2. L, R
|
||||||
3. L, R, C
|
3. L, R, C
|
||||||
4. FL, FR, B/SL, B/SR
|
4. FL, FR, B/SL, B/SR
|
||||||
5. FL, FR, C, B/SL, B/SR
|
5. FL, FR, C, B/SL, B/SR
|
||||||
6. FL, FR, C, LFE, B/SL, B/SR
|
6. FL, FR, C, LFE, B/SL, B/SR
|
||||||
7. FL, FR, C, LFE, B, SL, SR
|
7. FL, FR, C, LFE, B, SL, SR
|
||||||
8. FL, FR, C, LFE, BL, BR, SL, SR
|
8. FL, FR, C, LFE, BL, BR, SL, SR
|
||||||
|
|
||||||
QOA predicts each audio sample based on the previously decoded ones using a
|
QOA predicts each audio sample based on the previously decoded ones using a
|
||||||
"Sign-Sign Least Mean Squares Filter" (LMS). This prediction plus the
|
"Sign-Sign Least Mean Squares Filter" (LMS). This prediction plus the
|
||||||
dequantized residual forms the final output sample.
|
dequantized residual forms the final output sample.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
@ -178,9 +178,9 @@ typedef unsigned long long qoa_uint64_t;
|
||||||
|
|
||||||
|
|
||||||
/* The quant_tab provides an index into the dequant_tab for residuals in the
|
/* The quant_tab provides an index into the dequant_tab for residuals in the
|
||||||
range of -8 .. 8. It maps this range to just 3bits and becomes less accurate at
|
range of -8 .. 8. It maps this range to just 3bits and becomes less accurate at
|
||||||
the higher end. Note that the residual zero is identical to the lowest positive
|
the higher end. Note that the residual zero is identical to the lowest positive
|
||||||
value. This is mostly fine, since the qoa_div() function always rounds away
|
value. This is mostly fine, since the qoa_div() function always rounds away
|
||||||
from zero. */
|
from zero. */
|
||||||
|
|
||||||
static const int qoa_quant_tab[17] = {
|
static const int qoa_quant_tab[17] = {
|
||||||
|
|
@ -193,8 +193,8 @@ static const int qoa_quant_tab[17] = {
|
||||||
/* We have 16 different scalefactors. Like the quantized residuals these become
|
/* We have 16 different scalefactors. Like the quantized residuals these become
|
||||||
less accurate at the higher end. In theory, the highest scalefactor that we
|
less accurate at the higher end. In theory, the highest scalefactor that we
|
||||||
would need to encode the highest 16bit residual is (2**16)/8 = 8192. However we
|
would need to encode the highest 16bit residual is (2**16)/8 = 8192. However we
|
||||||
rely on the LMS filter to predict samples accurately enough that a maximum
|
rely on the LMS filter to predict samples accurately enough that a maximum
|
||||||
residual of one quarter of the 16 bit range is sufficient. I.e. with the
|
residual of one quarter of the 16 bit range is sufficient. I.e. with the
|
||||||
scalefactor 2048 times the quant range of 8 we can encode residuals up to 2**14.
|
scalefactor 2048 times the quant range of 8 we can encode residuals up to 2**14.
|
||||||
|
|
||||||
The scalefactor values are computed as:
|
The scalefactor values are computed as:
|
||||||
|
|
@ -205,9 +205,9 @@ static const int qoa_scalefactor_tab[16] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* The reciprocal_tab maps each of the 16 scalefactors to their rounded
|
/* The reciprocal_tab maps each of the 16 scalefactors to their rounded
|
||||||
reciprocals 1/scalefactor. This allows us to calculate the scaled residuals in
|
reciprocals 1/scalefactor. This allows us to calculate the scaled residuals in
|
||||||
the encoder with just one multiplication instead of an expensive division. We
|
the encoder with just one multiplication instead of an expensive division. We
|
||||||
do this in .16 fixed point with integers, instead of floats.
|
do this in .16 fixed point with integers, instead of floats.
|
||||||
|
|
||||||
The reciprocal_tab is computed as:
|
The reciprocal_tab is computed as:
|
||||||
|
|
@ -218,11 +218,11 @@ static const int qoa_reciprocal_tab[16] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* The dequant_tab maps each of the scalefactors and quantized residuals to
|
/* The dequant_tab maps each of the scalefactors and quantized residuals to
|
||||||
their unscaled & dequantized version.
|
their unscaled & dequantized version.
|
||||||
|
|
||||||
Since qoa_div rounds away from the zero, the smallest entries are mapped to 3/4
|
Since qoa_div rounds away from the zero, the smallest entries are mapped to 3/4
|
||||||
instead of 1. The dequant_tab assumes the following dequantized values for each
|
instead of 1. The dequant_tab assumes the following dequantized values for each
|
||||||
of the quant_tab indices and is computed as:
|
of the quant_tab indices and is computed as:
|
||||||
float dqt[8] = {0.75, -0.75, 2.5, -2.5, 4.5, -4.5, 7, -7};
|
float dqt[8] = {0.75, -0.75, 2.5, -2.5, 4.5, -4.5, 7, -7};
|
||||||
dequant_tab[s][q] <- round_ties_away_from_zero(scalefactor_tab[s] * dqt[q])
|
dequant_tab[s][q] <- round_ties_away_from_zero(scalefactor_tab[s] * dqt[q])
|
||||||
|
|
@ -258,7 +258,7 @@ adjusting 4 weights based on the residual of the previous prediction.
|
||||||
The next sample is predicted as the sum of (weight[i] * history[i]).
|
The next sample is predicted as the sum of (weight[i] * history[i]).
|
||||||
|
|
||||||
The adjustment of the weights is done with a "Sign-Sign-LMS" that adds or
|
The adjustment of the weights is done with a "Sign-Sign-LMS" that adds or
|
||||||
subtracts the residual to each weight, based on the corresponding sample from
|
subtracts the residual to each weight, based on the corresponding sample from
|
||||||
the history. This, surprisingly, is sufficient to get worthwhile predictions.
|
the history. This, surprisingly, is sufficient to get worthwhile predictions.
|
||||||
|
|
||||||
This is all done with fixed point integers. Hence the right-shifts when updating
|
This is all done with fixed point integers. Hence the right-shifts when updating
|
||||||
|
|
@ -285,8 +285,8 @@ static void qoa_lms_update(qoa_lms_t *lms, int sample, int residual) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* qoa_div() implements a rounding division, but avoids rounding to zero for
|
/* qoa_div() implements a rounding division, but avoids rounding to zero for
|
||||||
small numbers. E.g. 0.1 will be rounded to 1. Note that 0 itself still
|
small numbers. E.g. 0.1 will be rounded to 1. Note that 0 itself still
|
||||||
returns as 0, which is handled in the qoa_quant_tab[].
|
returns as 0, which is handled in the qoa_quant_tab[].
|
||||||
qoa_div() takes an index into the .16 fixed point qoa_reciprocal_tab as an
|
qoa_div() takes an index into the .16 fixed point qoa_reciprocal_tab as an
|
||||||
argument, so it can do the division with a cheaper integer multiplication. */
|
argument, so it can do the division with a cheaper integer multiplication. */
|
||||||
|
|
@ -385,10 +385,10 @@ unsigned int qoa_encode_frame(const short *sample_data, qoa_desc *qoa, unsigned
|
||||||
for (unsigned int c = 0; c < channels; c++) {
|
for (unsigned int c = 0; c < channels; c++) {
|
||||||
int slice_len = qoa_clamp(QOA_SLICE_LEN, 0, frame_len - sample_index);
|
int slice_len = qoa_clamp(QOA_SLICE_LEN, 0, frame_len - sample_index);
|
||||||
int slice_start = sample_index * channels + c;
|
int slice_start = sample_index * channels + c;
|
||||||
int slice_end = (sample_index + slice_len) * channels + c;
|
int slice_end = (sample_index + slice_len) * channels + c;
|
||||||
|
|
||||||
/* Brute for search for the best scalefactor. Just go through all
|
/* Brute force search for the best scalefactor. Just go through all
|
||||||
16 scalefactors, encode all samples for the current slice and
|
16 scalefactors, encode all samples for the current slice and
|
||||||
meassure the total squared error. */
|
meassure the total squared error. */
|
||||||
qoa_uint64_t best_rank = -1;
|
qoa_uint64_t best_rank = -1;
|
||||||
#ifdef QOA_RECORD_TOTAL_ERROR
|
#ifdef QOA_RECORD_TOTAL_ERROR
|
||||||
|
|
@ -402,7 +402,7 @@ unsigned int qoa_encode_frame(const short *sample_data, qoa_desc *qoa, unsigned
|
||||||
/* There is a strong correlation between the scalefactors of
|
/* There is a strong correlation between the scalefactors of
|
||||||
neighboring slices. As an optimization, start testing
|
neighboring slices. As an optimization, start testing
|
||||||
the best scalefactor of the previous slice first. */
|
the best scalefactor of the previous slice first. */
|
||||||
int scalefactor = (sfi + prev_scalefactor[c]) % 16;
|
int scalefactor = (sfi + prev_scalefactor[c]) & (16 - 1);
|
||||||
|
|
||||||
/* We have to reset the LMS state to the last known good one
|
/* We have to reset the LMS state to the last known good one
|
||||||
before trying each scalefactor, as each pass updates the LMS
|
before trying each scalefactor, as each pass updates the LMS
|
||||||
|
|
@ -500,7 +500,7 @@ void *qoa_encode(const short *sample_data, qoa_desc *qoa, unsigned int *out_len)
|
||||||
num_frames * QOA_LMS_LEN * 4 * qoa->channels + /* 4 * 4 bytes lms state per channel */
|
num_frames * QOA_LMS_LEN * 4 * qoa->channels + /* 4 * 4 bytes lms state per channel */
|
||||||
num_slices * 8 * qoa->channels; /* 8 byte slices */
|
num_slices * 8 * qoa->channels; /* 8 byte slices */
|
||||||
|
|
||||||
unsigned char *bytes = (unsigned char *)QOA_MALLOC(encoded_size);
|
unsigned char *bytes = QOA_MALLOC(encoded_size);
|
||||||
|
|
||||||
for (unsigned int c = 0; c < qoa->channels; c++) {
|
for (unsigned int c = 0; c < qoa->channels; c++) {
|
||||||
/* Set the initial LMS weights to {0, 0, -1, 2}. This helps with the
|
/* Set the initial LMS weights to {0, 0, -1, 2}. This helps with the
|
||||||
|
|
@ -657,7 +657,7 @@ short *qoa_decode(const unsigned char *bytes, int size, qoa_desc *qoa) {
|
||||||
|
|
||||||
/* Calculate the required size of the sample buffer and allocate */
|
/* Calculate the required size of the sample buffer and allocate */
|
||||||
int total_samples = qoa->samples * qoa->channels;
|
int total_samples = qoa->samples * qoa->channels;
|
||||||
short *sample_data = (short *)QOA_MALLOC(total_samples * sizeof(short));
|
short *sample_data = QOA_MALLOC(total_samples * sizeof(short));
|
||||||
|
|
||||||
unsigned int sample_index = 0;
|
unsigned int sample_index = 0;
|
||||||
unsigned int frame_len;
|
unsigned int frame_len;
|
||||||
|
|
@ -733,7 +733,7 @@ void *qoa_read(const char *filename, qoa_desc *qoa) {
|
||||||
bytes_read = fread(data, 1, size, f);
|
bytes_read = fread(data, 1, size, f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
sample_data = qoa_decode((const unsigned char *)data, bytes_read, qoa);
|
sample_data = qoa_decode(data, bytes_read, qoa);
|
||||||
QOA_FREE(data);
|
QOA_FREE(data);
|
||||||
return sample_data;
|
return sample_data;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
4
src/external/qoi.h
vendored
4
src/external/qoi.h
vendored
|
|
@ -427,7 +427,7 @@ void *qoi_encode(const void *data, const qoi_desc *desc, int *out_len) {
|
||||||
run = 0;
|
run = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
index_pos = QOI_COLOR_HASH(px) % 64;
|
index_pos = QOI_COLOR_HASH(px) & (64 - 1);
|
||||||
|
|
||||||
if (index[index_pos].v == px.v) {
|
if (index[index_pos].v == px.v) {
|
||||||
bytes[p++] = QOI_OP_INDEX | index_pos;
|
bytes[p++] = QOI_OP_INDEX | index_pos;
|
||||||
|
|
@ -574,7 +574,7 @@ void *qoi_decode(const void *data, int size, qoi_desc *desc, int channels) {
|
||||||
run = (b1 & 0x3f);
|
run = (b1 & 0x3f);
|
||||||
}
|
}
|
||||||
|
|
||||||
index[QOI_COLOR_HASH(px) % 64] = px;
|
index[QOI_COLOR_HASH(px) & (64 - 1)] = px;
|
||||||
}
|
}
|
||||||
|
|
||||||
pixels[px_pos + 0] = px.rgba.r;
|
pixels[px_pos + 0] = px.rgba.r;
|
||||||
|
|
|
||||||
662
src/external/stb_image_resize2.h
vendored
662
src/external/stb_image_resize2.h
vendored
File diff suppressed because it is too large
Load Diff
|
|
@ -821,6 +821,11 @@ void SetWindowSize(int width, int height)
|
||||||
CORE.Window.screen.height = height;
|
CORE.Window.screen.height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!CORE.Window.usingFbo)
|
||||||
|
{
|
||||||
|
SetupViewport(CORE.Window.screen.width, CORE.Window.screen.height);
|
||||||
|
}
|
||||||
|
|
||||||
RGFW_window_resize(platform.window, CORE.Window.screen.width, CORE.Window.screen.height);
|
RGFW_window_resize(platform.window, CORE.Window.screen.width, CORE.Window.screen.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
107
src/raudio.c
107
src/raudio.c
|
|
@ -963,20 +963,18 @@ Sound LoadSoundFromWave(Wave wave)
|
||||||
if (frameCount == 0) TRACELOG(LOG_WARNING, "SOUND: Failed to get frame count for format conversion");
|
if (frameCount == 0) TRACELOG(LOG_WARNING, "SOUND: Failed to get frame count for format conversion");
|
||||||
|
|
||||||
AudioBuffer *audioBuffer = LoadAudioBuffer(AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, frameCount, AUDIO_BUFFER_USAGE_STATIC);
|
AudioBuffer *audioBuffer = LoadAudioBuffer(AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, frameCount, AUDIO_BUFFER_USAGE_STATIC);
|
||||||
if (audioBuffer == NULL)
|
if (audioBuffer != NULL)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "SOUND: Failed to create buffer");
|
frameCount = (ma_uint32)ma_convert_frames(audioBuffer->data, frameCount, AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, wave.data, frameCountIn, formatIn, wave.channels, wave.sampleRate);
|
||||||
return sound; // early return to avoid dereferencing the audioBuffer null pointer
|
if (frameCount == 0) TRACELOG(LOG_WARNING, "SOUND: Failed format conversion");
|
||||||
|
|
||||||
|
sound.frameCount = frameCount;
|
||||||
|
sound.stream.sampleRate = AUDIO.System.device.sampleRate;
|
||||||
|
sound.stream.sampleSize = 32;
|
||||||
|
sound.stream.channels = AUDIO_DEVICE_CHANNELS;
|
||||||
|
sound.stream.buffer = audioBuffer;
|
||||||
}
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "SOUND: Failed to create buffer");
|
||||||
frameCount = (ma_uint32)ma_convert_frames(audioBuffer->data, frameCount, AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, wave.data, frameCountIn, formatIn, wave.channels, wave.sampleRate);
|
|
||||||
if (frameCount == 0) TRACELOG(LOG_WARNING, "SOUND: Failed format conversion");
|
|
||||||
|
|
||||||
sound.frameCount = frameCount;
|
|
||||||
sound.stream.sampleRate = AUDIO.System.device.sampleRate;
|
|
||||||
sound.stream.sampleSize = 32;
|
|
||||||
sound.stream.channels = AUDIO_DEVICE_CHANNELS;
|
|
||||||
sound.stream.buffer = audioBuffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sound;
|
return sound;
|
||||||
|
|
@ -992,25 +990,23 @@ Sound LoadSoundAlias(Sound source)
|
||||||
{
|
{
|
||||||
AudioBuffer *audioBuffer = LoadAudioBuffer(AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, 0, AUDIO_BUFFER_USAGE_STATIC);
|
AudioBuffer *audioBuffer = LoadAudioBuffer(AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, 0, AUDIO_BUFFER_USAGE_STATIC);
|
||||||
|
|
||||||
if (audioBuffer == NULL)
|
if (audioBuffer != NULL)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "SOUND: Failed to create buffer");
|
audioBuffer->sizeInFrames = source.stream.buffer->sizeInFrames;
|
||||||
return sound; // Early return to avoid dereferencing the audioBuffer null pointer
|
audioBuffer->data = source.stream.buffer->data;
|
||||||
|
|
||||||
|
// Initalize the buffer as if it was new
|
||||||
|
audioBuffer->volume = 1.0f;
|
||||||
|
audioBuffer->pitch = 1.0f;
|
||||||
|
audioBuffer->pan = 0.0f; // Center
|
||||||
|
|
||||||
|
sound.frameCount = source.frameCount;
|
||||||
|
sound.stream.sampleRate = AUDIO.System.device.sampleRate;
|
||||||
|
sound.stream.sampleSize = 32;
|
||||||
|
sound.stream.channels = AUDIO_DEVICE_CHANNELS;
|
||||||
|
sound.stream.buffer = audioBuffer;
|
||||||
}
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "SOUND: Failed to create buffer");
|
||||||
audioBuffer->sizeInFrames = source.stream.buffer->sizeInFrames;
|
|
||||||
audioBuffer->data = source.stream.buffer->data;
|
|
||||||
|
|
||||||
// Initalize the buffer as if it was new
|
|
||||||
audioBuffer->volume = 1.0f;
|
|
||||||
audioBuffer->pitch = 1.0f;
|
|
||||||
audioBuffer->pan = 0.0f; // Center
|
|
||||||
|
|
||||||
sound.frameCount = source.frameCount;
|
|
||||||
sound.stream.sampleRate = AUDIO.System.device.sampleRate;
|
|
||||||
sound.stream.sampleSize = 32;
|
|
||||||
sound.stream.channels = AUDIO_DEVICE_CHANNELS;
|
|
||||||
sound.stream.buffer = audioBuffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sound;
|
return sound;
|
||||||
|
|
@ -1071,7 +1067,7 @@ void UpdateSound(Sound sound, const void *data, int frameCount)
|
||||||
// Export wave data to file
|
// Export wave data to file
|
||||||
bool ExportWave(Wave wave, const char *fileName)
|
bool ExportWave(Wave wave, const char *fileName)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool result = false;
|
||||||
|
|
||||||
if (false) { }
|
if (false) { }
|
||||||
#if SUPPORT_FILEFORMAT_WAV
|
#if SUPPORT_FILEFORMAT_WAV
|
||||||
|
|
@ -1088,11 +1084,11 @@ bool ExportWave(Wave wave, const char *fileName)
|
||||||
|
|
||||||
void *fileData = NULL;
|
void *fileData = NULL;
|
||||||
size_t fileDataSize = 0;
|
size_t fileDataSize = 0;
|
||||||
success = drwav_init_memory_write(&wav, &fileData, &fileDataSize, &format, NULL);
|
result = drwav_init_memory_write(&wav, &fileData, &fileDataSize, &format, NULL);
|
||||||
if (success) success = (int)drwav_write_pcm_frames(&wav, wave.frameCount, wave.data);
|
if (result) result = (int)drwav_write_pcm_frames(&wav, wave.frameCount, wave.data);
|
||||||
drwav_result result = drwav_uninit(&wav);
|
drwav_result result = drwav_uninit(&wav);
|
||||||
|
|
||||||
if (result == DRWAV_SUCCESS) success = SaveFileData(fileName, (unsigned char *)fileData, (unsigned int)fileDataSize);
|
if (result == DRWAV_SUCCESS) result = SaveFileData(fileName, (unsigned char *)fileData, (unsigned int)fileDataSize);
|
||||||
|
|
||||||
drwav_free(fileData, NULL);
|
drwav_free(fileData, NULL);
|
||||||
}
|
}
|
||||||
|
|
@ -1108,7 +1104,7 @@ bool ExportWave(Wave wave, const char *fileName)
|
||||||
qoa.samples = wave.frameCount;
|
qoa.samples = wave.frameCount;
|
||||||
|
|
||||||
int bytesWritten = qoa_write(fileName, (const short *)wave.data, &qoa);
|
int bytesWritten = qoa_write(fileName, (const short *)wave.data, &qoa);
|
||||||
if (bytesWritten > 0) success = true;
|
if (bytesWritten > 0) result = true;
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "AUDIO: Wave data must be 16 bit per sample for QOA format export");
|
else TRACELOG(LOG_WARNING, "AUDIO: Wave data must be 16 bit per sample for QOA format export");
|
||||||
}
|
}
|
||||||
|
|
@ -1117,19 +1113,19 @@ bool ExportWave(Wave wave, const char *fileName)
|
||||||
{
|
{
|
||||||
// Export raw sample data (without header)
|
// Export raw sample data (without header)
|
||||||
// NOTE: It's up to the user to track wave parameters
|
// NOTE: It's up to the user to track wave parameters
|
||||||
success = SaveFileData(fileName, wave.data, wave.frameCount*wave.channels*wave.sampleSize/8);
|
result = SaveFileData(fileName, wave.data, wave.frameCount*wave.channels*wave.sampleSize/8);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success) TRACELOG(LOG_INFO, "FILEIO: [%s] Wave data exported successfully", fileName);
|
if (result) TRACELOG(LOG_INFO, "FILEIO: [%s] Wave data exported successfully", fileName);
|
||||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export wave data", fileName);
|
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export wave data", fileName);
|
||||||
|
|
||||||
return success;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export wave sample data to code (.h)
|
// Export wave sample data to code (.h)
|
||||||
bool ExportWaveAsCode(Wave wave, const char *fileName)
|
bool ExportWaveAsCode(Wave wave, const char *fileName)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool result = false;
|
||||||
|
|
||||||
#ifndef TEXT_BYTES_PER_LINE
|
#ifndef TEXT_BYTES_PER_LINE
|
||||||
#define TEXT_BYTES_PER_LINE 20
|
#define TEXT_BYTES_PER_LINE 20
|
||||||
|
|
@ -1183,14 +1179,14 @@ bool ExportWaveAsCode(Wave wave, const char *fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Text data length exported is determined by '\0' (NULL) character
|
// NOTE: Text data length exported is determined by '\0' (NULL) character
|
||||||
success = SaveFileText(fileName, txtData);
|
result = SaveFileText(fileName, txtData);
|
||||||
|
|
||||||
RL_FREE(txtData);
|
RL_FREE(txtData);
|
||||||
|
|
||||||
if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Wave as code exported successfully", fileName);
|
if (result != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Wave as code exported successfully", fileName);
|
||||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export wave as code", fileName);
|
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export wave as code", fileName);
|
||||||
|
|
||||||
return success;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Play a sound
|
// Play a sound
|
||||||
|
|
@ -2187,12 +2183,15 @@ void UpdateAudioStream(AudioStream stream, const void *data, int frameCount)
|
||||||
// Check if any audio stream buffers requires refill
|
// Check if any audio stream buffers requires refill
|
||||||
bool IsAudioStreamProcessed(AudioStream stream)
|
bool IsAudioStreamProcessed(AudioStream stream)
|
||||||
{
|
{
|
||||||
if (stream.buffer == NULL) return false;
|
|
||||||
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
ma_mutex_lock(&AUDIO.System.lock);
|
|
||||||
result = stream.buffer->isSubBufferProcessed[0] || stream.buffer->isSubBufferProcessed[1];
|
if (stream.buffer != NULL)
|
||||||
ma_mutex_unlock(&AUDIO.System.lock);
|
{
|
||||||
|
ma_mutex_lock(&AUDIO.System.lock);
|
||||||
|
result = stream.buffer->isSubBufferProcessed[0] || stream.buffer->isSubBufferProcessed[1];
|
||||||
|
ma_mutex_unlock(&AUDIO.System.lock);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2885,6 +2884,8 @@ static unsigned char *LoadFileData(const char *fileName, int *dataSize)
|
||||||
// Save data to file from buffer
|
// Save data to file from buffer
|
||||||
static bool SaveFileData(const char *fileName, void *data, int dataSize)
|
static bool SaveFileData(const char *fileName, void *data, int dataSize)
|
||||||
{
|
{
|
||||||
|
bool result = true;
|
||||||
|
|
||||||
if (fileName != NULL)
|
if (fileName != NULL)
|
||||||
{
|
{
|
||||||
FILE *file = fopen(fileName, "wb");
|
FILE *file = fopen(fileName, "wb");
|
||||||
|
|
@ -2902,21 +2903,23 @@ static bool SaveFileData(const char *fileName, void *data, int dataSize)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open file", fileName);
|
TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open file", fileName);
|
||||||
return false;
|
result = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
|
TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
|
||||||
return false;
|
result = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save text data to file (write), string must be '\0' terminated
|
// Save text data to file (write), string must be '\0' terminated
|
||||||
static bool SaveFileText(const char *fileName, char *text)
|
static bool SaveFileText(const char *fileName, char *text)
|
||||||
{
|
{
|
||||||
|
bool result = true;
|
||||||
|
|
||||||
if (fileName != NULL)
|
if (fileName != NULL)
|
||||||
{
|
{
|
||||||
FILE *file = fopen(fileName, "wt");
|
FILE *file = fopen(fileName, "wt");
|
||||||
|
|
@ -2934,16 +2937,16 @@ static bool SaveFileText(const char *fileName, char *text)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open text file", fileName);
|
TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open text file", fileName);
|
||||||
return false;
|
result = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
|
TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
|
||||||
return false;
|
result = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return result;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
19
src/raylib.h
19
src/raylib.h
|
|
@ -1161,8 +1161,8 @@ RLAPI int MakeDirectory(const char *dirPath); // Create di
|
||||||
RLAPI bool ChangeDirectory(const char *dirPath); // Change working directory, return true on success
|
RLAPI bool ChangeDirectory(const char *dirPath); // Change working directory, return true on success
|
||||||
RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory
|
RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory
|
||||||
RLAPI bool IsFileNameValid(const char *fileName); // Check if fileName is valid for the platform/OS
|
RLAPI bool IsFileNameValid(const char *fileName); // Check if fileName is valid for the platform/OS
|
||||||
RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths
|
RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths, files and directories, no subdirs scan
|
||||||
RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result
|
RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and subdir scan; some filters available: "*.*", "FILES*", "DIRS*"
|
||||||
RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload filepaths
|
RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload filepaths
|
||||||
RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window
|
RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window
|
||||||
RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths
|
RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths
|
||||||
|
|
@ -1359,7 +1359,7 @@ RLAPI Image LoadImageFromScreen(void);
|
||||||
RLAPI bool IsImageValid(Image image); // Check if an image is valid (data and parameters)
|
RLAPI bool IsImageValid(Image image); // Check if an image is valid (data and parameters)
|
||||||
RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM)
|
RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM)
|
||||||
RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success
|
RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success
|
||||||
RLAPI unsigned char *ExportImageToMemory(Image image, const char *fileType, int *fileSize); // Export image to memory buffer
|
RLAPI unsigned char *ExportImageToMemory(Image image, const char *fileType, int *fileSize); // Export image to memory buffer, memory must be MemFree()
|
||||||
RLAPI bool ExportImageAsCode(Image image, const char *fileName); // Export image as code file defining an array of bytes, returns true on success
|
RLAPI bool ExportImageAsCode(Image image, const char *fileName); // Export image as code file defining an array of bytes, returns true on success
|
||||||
|
|
||||||
// Image generation functions
|
// Image generation functions
|
||||||
|
|
@ -1528,7 +1528,7 @@ RLAPI const char *CodepointToUTF8(int codepoint, int *utf8Size);
|
||||||
|
|
||||||
// Text strings management functions (no UTF-8 strings, only byte chars)
|
// Text strings management functions (no UTF-8 strings, only byte chars)
|
||||||
// WARNING 1: Most of these functions use internal static buffers[], it's recommended to store returned data on user-side for re-use
|
// WARNING 1: Most of these functions use internal static buffers[], it's recommended to store returned data on user-side for re-use
|
||||||
// WARNING 2: Some strings allocate memory internally for the returned strings, those strings must be free by user using MemFree()
|
// WARNING 2: Some functions allocate memory internally for the returned strings, those strings must be freed by user using MemFree()
|
||||||
RLAPI char **LoadTextLines(const char *text, int *count); // Load text as separate lines ('\n')
|
RLAPI char **LoadTextLines(const char *text, int *count); // Load text as separate lines ('\n')
|
||||||
RLAPI void UnloadTextLines(char **text, int lineCount); // Unload text lines
|
RLAPI void UnloadTextLines(char **text, int lineCount); // Unload text lines
|
||||||
RLAPI int TextCopy(char *dst, const char *src); // Copy one string to another, returns bytes copied
|
RLAPI int TextCopy(char *dst, const char *src); // Copy one string to another, returns bytes copied
|
||||||
|
|
@ -1538,9 +1538,12 @@ RLAPI const char *TextFormat(const char *text, ...);
|
||||||
RLAPI const char *TextSubtext(const char *text, int position, int length); // Get a piece of a text string
|
RLAPI const char *TextSubtext(const char *text, int position, int length); // Get a piece of a text string
|
||||||
RLAPI const char *TextRemoveSpaces(const char *text); // Remove text spaces, concat words
|
RLAPI const char *TextRemoveSpaces(const char *text); // Remove text spaces, concat words
|
||||||
RLAPI char *GetTextBetween(const char *text, const char *begin, const char *end); // Get text between two strings
|
RLAPI char *GetTextBetween(const char *text, const char *begin, const char *end); // Get text between two strings
|
||||||
RLAPI char *TextReplace(const char *text, const char *search, const char *replacement); // Replace text string (WARNING: memory must be freed!)
|
RLAPI char *TextReplace(const char *text, const char *search, const char *replacement); // Replace text string with new string
|
||||||
RLAPI char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replacement); // Replace text between two specific strings (WARNING: memory must be freed!)
|
RLAPI char *TextReplaceAlloc(const char *text, const char *search, const char *replacement); // Replace text string with new string, memory must be MemFree()
|
||||||
RLAPI char *TextInsert(const char *text, const char *insert, int position); // Insert text in a position (WARNING: memory must be freed!)
|
RLAPI char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replacement); // Replace text between two specific strings
|
||||||
|
RLAPI char *TextReplaceBetweenAlloc(const char *text, const char *begin, const char *end, const char *replacement); // Replace text between two specific strings, memory must be MemFree()
|
||||||
|
RLAPI char *TextInsert(const char *text, const char *insert, int position); // Insert text in a defined byte position
|
||||||
|
RLAPI char *TextInsertAlloc(const char *text, const char *insert, int position); // Insert text in a defined byte position, memory must be MemFree()
|
||||||
RLAPI char *TextJoin(char **textList, int count, const char *delimiter); // Join text strings with delimiter
|
RLAPI char *TextJoin(char **textList, int count, const char *delimiter); // Join text strings with delimiter
|
||||||
RLAPI char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings, using MAX_TEXTSPLIT_COUNT static strings
|
RLAPI char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings, using MAX_TEXTSPLIT_COUNT static strings
|
||||||
RLAPI void TextAppend(char *text, const char *append, int *position); // Append text at specific position and move cursor
|
RLAPI void TextAppend(char *text, const char *append, int *position); // Append text at specific position and move cursor
|
||||||
|
|
@ -1596,8 +1599,6 @@ RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint);
|
||||||
RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters
|
RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters
|
||||||
RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set)
|
RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set)
|
||||||
RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters
|
RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters
|
||||||
RLAPI void DrawModelPoints(Model model, Vector3 position, float scale, Color tint); // Draw a model as points
|
|
||||||
RLAPI void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model as points with extended parameters
|
|
||||||
RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires)
|
RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires)
|
||||||
RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture
|
RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture
|
||||||
RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source
|
RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source
|
||||||
|
|
|
||||||
88
src/rcore.c
88
src/rcore.c
|
|
@ -267,15 +267,18 @@
|
||||||
#define MAX_AUTOMATION_EVENTS 16384 // Maximum number of automation events to record
|
#define MAX_AUTOMATION_EVENTS 16384 // Maximum number of automation events to record
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// File and directory scan filters
|
||||||
|
// NOTE: Used in ScanDirectoryFiles(), LoadDirectoryFilesEx() and GetDirectoryFileCountEx()
|
||||||
|
// WARNING: Custom file filters can be specified but following raylib IsFileExtension() convention: ".png;.wav;.glb"
|
||||||
#ifndef FILE_FILTER_TAG_ALL
|
#ifndef FILE_FILTER_TAG_ALL
|
||||||
#define FILE_FILTER_TAG_ALL "*.*" // Filter to include all file types and directories on directory scan
|
#define FILE_FILTER_TAG_ALL "*.*" // Filter to include all file types and directories on scan
|
||||||
#endif // NOTE: Used in ScanDirectoryFiles(), LoadDirectoryFilesEx() and GetDirectoryFileCountEx()
|
#endif
|
||||||
#ifndef FILE_FILTER_TAG_FILE_ONLY
|
#ifndef FILE_FILTER_TAG_FILE_ONLY
|
||||||
#define FILE_FILTER_TAG_FILE_ONLY "FILES*" // Filter to include all file types on directory scan
|
#define FILE_FILTER_TAG_FILE_ONLY "FILES*" // Filter to include all file types on scan (no directories)
|
||||||
#endif // NOTE: Used in ScanDirectoryFiles(), LoadDirectoryFilesEx() and GetDirectoryFileCountEx()
|
#endif
|
||||||
#ifndef FILE_FILTER_TAG_DIR_ONLY
|
#ifndef FILE_FILTER_TAG_DIR_ONLY
|
||||||
#define FILE_FILTER_TAG_DIR_ONLY "DIR*" // Filter to include directories on directory scan
|
#define FILE_FILTER_TAG_DIR_ONLY "DIRS*" // Filter to include only directories on scan
|
||||||
#endif // NOTE: Used in ScanDirectoryFiles(), LoadDirectoryFilesEx() and GetDirectoryFileCountEx()
|
#endif
|
||||||
|
|
||||||
// Flags bitwise operation macros
|
// Flags bitwise operation macros
|
||||||
#define FLAG_SET(n, f) ((n) |= (f))
|
#define FLAG_SET(n, f) ((n) |= (f))
|
||||||
|
|
@ -821,7 +824,7 @@ int GetRenderWidth(void)
|
||||||
{
|
{
|
||||||
int width = 0;
|
int width = 0;
|
||||||
|
|
||||||
if (CORE.Window.usingFbo) return CORE.Window.currentFbo.width;
|
if (CORE.Window.usingFbo) width = CORE.Window.currentFbo.width;
|
||||||
else width = CORE.Window.render.width;
|
else width = CORE.Window.render.width;
|
||||||
|
|
||||||
return width;
|
return width;
|
||||||
|
|
@ -832,7 +835,7 @@ int GetRenderHeight(void)
|
||||||
{
|
{
|
||||||
int height = 0;
|
int height = 0;
|
||||||
|
|
||||||
if (CORE.Window.usingFbo) return CORE.Window.currentFbo.height;
|
if (CORE.Window.usingFbo) height = CORE.Window.currentFbo.height;
|
||||||
else height = CORE.Window.render.height;
|
else height = CORE.Window.render.height;
|
||||||
|
|
||||||
return height;
|
return height;
|
||||||
|
|
@ -1227,7 +1230,7 @@ void UnloadVrStereoConfig(VrStereoConfig config)
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Load shader from files and bind default locations
|
// Load shader from files and bind default locations
|
||||||
// NOTE: If shader string is NULL, using default vertex/fragment shaders
|
// NOTE: If shader filename is NULL, using default vertex/fragment shaders
|
||||||
Shader LoadShader(const char *vsFileName, const char *fsFileName)
|
Shader LoadShader(const char *vsFileName, const char *fsFileName)
|
||||||
{
|
{
|
||||||
Shader shader = { 0 };
|
Shader shader = { 0 };
|
||||||
|
|
@ -1621,18 +1624,20 @@ int GetFPS(void)
|
||||||
for (int i = 0; i < FPS_CAPTURE_FRAMES_COUNT; i++) history[i] = 0;
|
for (int i = 0; i < FPS_CAPTURE_FRAMES_COUNT; i++) history[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fpsFrame == 0) return 0;
|
if (fpsFrame != 0)
|
||||||
|
|
||||||
if ((GetTime() - last) > FPS_STEP)
|
|
||||||
{
|
{
|
||||||
last = (float)GetTime();
|
if ((GetTime() - last) > FPS_STEP)
|
||||||
index = (index + 1)%FPS_CAPTURE_FRAMES_COUNT;
|
{
|
||||||
average -= history[index];
|
last = (float)GetTime();
|
||||||
history[index] = fpsFrame/FPS_CAPTURE_FRAMES_COUNT;
|
index = (index + 1)%FPS_CAPTURE_FRAMES_COUNT;
|
||||||
average += history[index];
|
average -= history[index];
|
||||||
}
|
history[index] = fpsFrame/FPS_CAPTURE_FRAMES_COUNT;
|
||||||
|
average += history[index];
|
||||||
|
}
|
||||||
|
|
||||||
fps = (int)roundf(1.0f/average);
|
fps = (int)roundf(1.0f/average);
|
||||||
|
}
|
||||||
|
else fps = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return fps;
|
return fps;
|
||||||
|
|
@ -2025,7 +2030,7 @@ void UnloadFileData(unsigned char *data)
|
||||||
// Save data to file from buffer
|
// Save data to file from buffer
|
||||||
bool SaveFileData(const char *fileName, void *data, int dataSize)
|
bool SaveFileData(const char *fileName, void *data, int dataSize)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool result = false;
|
||||||
|
|
||||||
if (fileName != NULL)
|
if (fileName != NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -2043,20 +2048,20 @@ bool SaveFileData(const char *fileName, void *data, int dataSize)
|
||||||
else if (count != dataSize) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially written", fileName);
|
else if (count != dataSize) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially written", fileName);
|
||||||
else TRACELOG(LOG_INFO, "FILEIO: [%s] File saved successfully", fileName);
|
else TRACELOG(LOG_INFO, "FILEIO: [%s] File saved successfully", fileName);
|
||||||
|
|
||||||
int result = fclose(file);
|
int closed = fclose(file);
|
||||||
if (result == 0) success = true;
|
if (closed == 0) result = true;
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open file", fileName);
|
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open file", fileName);
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
|
else TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
|
||||||
|
|
||||||
return success;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export data to code (.h), returns true on success
|
// Export data to code (.h), returns true on success
|
||||||
bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName)
|
bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool result = false;
|
||||||
|
|
||||||
#ifndef TEXT_BYTES_PER_LINE
|
#ifndef TEXT_BYTES_PER_LINE
|
||||||
#define TEXT_BYTES_PER_LINE 20
|
#define TEXT_BYTES_PER_LINE 20
|
||||||
|
|
@ -2096,14 +2101,14 @@ bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileN
|
||||||
byteCount += sprintf(txtData + byteCount, "0x%x };\n", data[dataSize - 1]);
|
byteCount += sprintf(txtData + byteCount, "0x%x };\n", data[dataSize - 1]);
|
||||||
|
|
||||||
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
||||||
success = SaveFileText(fileName, txtData);
|
result = SaveFileText(fileName, txtData);
|
||||||
|
|
||||||
RL_FREE(txtData);
|
RL_FREE(txtData);
|
||||||
|
|
||||||
if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Data as code exported successfully", fileName);
|
if (result != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Data as code exported successfully", fileName);
|
||||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export data as code", fileName);
|
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export data as code", fileName);
|
||||||
|
|
||||||
return success;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load text data from file, returns a '\0' terminated string
|
// Load text data from file, returns a '\0' terminated string
|
||||||
|
|
@ -2166,7 +2171,7 @@ void UnloadFileText(char *text)
|
||||||
// Save text data to file (write), string must be '\0' terminated
|
// Save text data to file (write), string must be '\0' terminated
|
||||||
bool SaveFileText(const char *fileName, const char *text)
|
bool SaveFileText(const char *fileName, const char *text)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool result = false;
|
||||||
|
|
||||||
if (fileName != NULL)
|
if (fileName != NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -2181,14 +2186,14 @@ bool SaveFileText(const char *fileName, const char *text)
|
||||||
if (count < 0) TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to write text file", fileName);
|
if (count < 0) TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to write text file", fileName);
|
||||||
else TRACELOG(LOG_INFO, "FILEIO: [%s] Text file saved successfully", fileName);
|
else TRACELOG(LOG_INFO, "FILEIO: [%s] Text file saved successfully", fileName);
|
||||||
|
|
||||||
int result = fclose(file);
|
int closed = fclose(file);
|
||||||
if (result == 0) success = true;
|
if (closed == 0) result = true;
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open text file", fileName);
|
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open text file", fileName);
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
|
else TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
|
||||||
|
|
||||||
return success;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// File access custom callbacks
|
// File access custom callbacks
|
||||||
|
|
@ -2298,7 +2303,7 @@ int FileTextReplace(const char *fileName, const char *search, const char *replac
|
||||||
if (FileExists(fileName))
|
if (FileExists(fileName))
|
||||||
{
|
{
|
||||||
fileText = LoadFileText(fileName);
|
fileText = LoadFileText(fileName);
|
||||||
fileTextUpdated = TextReplace(fileText, search, replacement);
|
fileTextUpdated = TextReplaceAlloc(fileText, search, replacement);
|
||||||
result = SaveFileText(fileName, fileTextUpdated);
|
result = SaveFileText(fileName, fileTextUpdated);
|
||||||
MemFree(fileTextUpdated);
|
MemFree(fileTextUpdated);
|
||||||
UnloadFileText(fileText);
|
UnloadFileText(fileText);
|
||||||
|
|
@ -2718,17 +2723,18 @@ const char *GetApplicationDirectory(void)
|
||||||
|
|
||||||
// Load directory filepaths
|
// Load directory filepaths
|
||||||
// NOTE: Base path is prepended to the scanned filepaths
|
// NOTE: Base path is prepended to the scanned filepaths
|
||||||
// WARNING: Directory is scanned twice, first time to get files count
|
// WARNING: Directory is scanned twice, first time to get paths count
|
||||||
// No recursive scanning is done!
|
// Scanneed files and directories, no recursive/subdirs scanning
|
||||||
FilePathList LoadDirectoryFiles(const char *dirPath)
|
FilePathList LoadDirectoryFiles(const char *dirPath)
|
||||||
{
|
{
|
||||||
return LoadDirectoryFilesEx(dirPath, FILE_FILTER_TAG_ALL, false);
|
return LoadDirectoryFilesEx(dirPath, FILE_FILTER_TAG_ALL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load directory filepaths with extension filtering and recursive directory scan
|
// Load directory filepaths with extension filtering and recursive directory scan
|
||||||
// Use 'DIR*' to include directories on directory scan
|
// Use "*.*" to include all files and directories on scan
|
||||||
// Use '*.*' to include all file types and directories on directory scan
|
// Use "FILES*" to include only files on scan
|
||||||
// WARNING: Directory is scanned twice, first time to get files count
|
// Use "DIRS*" to include only directories on scan
|
||||||
|
// WARNING: Directory is scanned twice, first time to get paths count
|
||||||
FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs)
|
FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs)
|
||||||
{
|
{
|
||||||
FilePathList files = { 0 };
|
FilePathList files = { 0 };
|
||||||
|
|
@ -3628,7 +3634,7 @@ void UnloadAutomationEventList(AutomationEventList list)
|
||||||
// Export automation events list as text file
|
// Export automation events list as text file
|
||||||
bool ExportAutomationEventList(AutomationEventList list, const char *fileName)
|
bool ExportAutomationEventList(AutomationEventList list, const char *fileName)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool result = false;
|
||||||
|
|
||||||
#if SUPPORT_AUTOMATION_EVENTS
|
#if SUPPORT_AUTOMATION_EVENTS
|
||||||
// Export events as binary file
|
// Export events as binary file
|
||||||
|
|
@ -3646,7 +3652,7 @@ bool ExportAutomationEventList(AutomationEventList list, const char *fileName)
|
||||||
memcpy(binBuffer + offset, list.events, sizeof(AutomationEvent)*list.count);
|
memcpy(binBuffer + offset, list.events, sizeof(AutomationEvent)*list.count);
|
||||||
offset += sizeof(AutomationEvent)*list.count;
|
offset += sizeof(AutomationEvent)*list.count;
|
||||||
|
|
||||||
success = SaveFileData(TextFormat("%s.rae",fileName), binBuffer, binarySize);
|
result = SaveFileData(TextFormat("%s.rae",fileName), binBuffer, binarySize);
|
||||||
RL_FREE(binBuffer);
|
RL_FREE(binBuffer);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
@ -3677,12 +3683,12 @@ bool ExportAutomationEventList(AutomationEventList list, const char *fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
||||||
success = SaveFileText(fileName, txtData);
|
result = SaveFileText(fileName, txtData);
|
||||||
|
|
||||||
RL_FREE(txtData);
|
RL_FREE(txtData);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return success;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup automation event list to record to
|
// Setup automation event list to record to
|
||||||
|
|
|
||||||
12
src/rlgl.h
12
src/rlgl.h
|
|
@ -1613,6 +1613,11 @@ void rlNormal3f(float x, float y, float z)
|
||||||
normaly = RLGL.State.transform.m1*x + RLGL.State.transform.m5*y + RLGL.State.transform.m9*z;
|
normaly = RLGL.State.transform.m1*x + RLGL.State.transform.m5*y + RLGL.State.transform.m9*z;
|
||||||
normalz = RLGL.State.transform.m2*x + RLGL.State.transform.m6*y + RLGL.State.transform.m10*z;
|
normalz = RLGL.State.transform.m2*x + RLGL.State.transform.m6*y + RLGL.State.transform.m10*z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: Default behavior assumes the normal vector is in the correct space for what the shader expects,
|
||||||
|
// it could be not normalized to 0.0f..1.0f, magnitud can be useed for some effects
|
||||||
|
/*
|
||||||
|
// WARNING: Vector normalization if required
|
||||||
float length = sqrtf(normalx*normalx + normaly*normaly + normalz*normalz);
|
float length = sqrtf(normalx*normalx + normaly*normaly + normalz*normalz);
|
||||||
if (length != 0.0f)
|
if (length != 0.0f)
|
||||||
{
|
{
|
||||||
|
|
@ -1621,6 +1626,7 @@ void rlNormal3f(float x, float y, float z)
|
||||||
normaly *= ilength;
|
normaly *= ilength;
|
||||||
normalz *= ilength;
|
normalz *= ilength;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
RLGL.State.normalx = normalx;
|
RLGL.State.normalx = normalx;
|
||||||
RLGL.State.normaly = normaly;
|
RLGL.State.normaly = normaly;
|
||||||
RLGL.State.normalz = normalz;
|
RLGL.State.normalz = normalz;
|
||||||
|
|
@ -4647,14 +4653,14 @@ void rlUpdateShaderBuffer(unsigned int id, const void *data, unsigned int dataSi
|
||||||
// Get SSBO buffer size
|
// Get SSBO buffer size
|
||||||
unsigned int rlGetShaderBufferSize(unsigned int id)
|
unsigned int rlGetShaderBufferSize(unsigned int id)
|
||||||
{
|
{
|
||||||
|
unsigned int result = 0;
|
||||||
#if defined(GRAPHICS_API_OPENGL_43)
|
#if defined(GRAPHICS_API_OPENGL_43)
|
||||||
GLint64 size = 0;
|
GLint64 size = 0;
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, id);
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, id);
|
||||||
glGetBufferParameteri64v(GL_SHADER_STORAGE_BUFFER, GL_BUFFER_SIZE, &size);
|
glGetBufferParameteri64v(GL_SHADER_STORAGE_BUFFER, GL_BUFFER_SIZE, &size);
|
||||||
return (size > 0)? (unsigned int)size : 0;
|
if (size > 0) result = (unsigned int)size;
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
#endif
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read SSBO buffer data (GPU->CPU)
|
// Read SSBO buffer data (GPU->CPU)
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
* #define SUPPORT_FILEFORMAT_MTL
|
* #define SUPPORT_FILEFORMAT_MTL
|
||||||
* #define SUPPORT_FILEFORMAT_IQM
|
* #define SUPPORT_FILEFORMAT_IQM
|
||||||
* #define SUPPORT_FILEFORMAT_GLTF
|
* #define SUPPORT_FILEFORMAT_GLTF
|
||||||
|
* #define SUPPORT_FILEFORMAT_GLTF_WRITE
|
||||||
* #define SUPPORT_FILEFORMAT_VOX
|
* #define SUPPORT_FILEFORMAT_VOX
|
||||||
* #define SUPPORT_FILEFORMAT_M3D
|
* #define SUPPORT_FILEFORMAT_M3D
|
||||||
* Selected desired fileformats to be supported for model data loading
|
* Selected desired fileformats to be supported for model data loading
|
||||||
|
|
@ -71,6 +72,11 @@
|
||||||
#define CGLTF_IMPLEMENTATION
|
#define CGLTF_IMPLEMENTATION
|
||||||
#include "external/cgltf.h" // glTF file format loading
|
#include "external/cgltf.h" // glTF file format loading
|
||||||
#endif
|
#endif
|
||||||
|
#if SUPPORT_FILEFORMAT_GLTF_WRITE
|
||||||
|
// NOTE: No need for custom allocators, memory buffer provided
|
||||||
|
#define CGLTF_WRITE_IMPLEMENTATION
|
||||||
|
#include "external/cgltf_write.h" // glTF file format writing
|
||||||
|
#endif
|
||||||
|
|
||||||
#if SUPPORT_FILEFORMAT_VOX
|
#if SUPPORT_FILEFORMAT_VOX
|
||||||
#define VOX_MALLOC RL_MALLOC
|
#define VOX_MALLOC RL_MALLOC
|
||||||
|
|
@ -1281,7 +1287,6 @@ void UploadMesh(Mesh *mesh, bool dynamic)
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
mesh->vaoId = rlLoadVertexArray();
|
mesh->vaoId = rlLoadVertexArray();
|
||||||
if (mesh->vaoId == 0) return;
|
|
||||||
|
|
||||||
rlEnableVertexArray(mesh->vaoId);
|
rlEnableVertexArray(mesh->vaoId);
|
||||||
|
|
||||||
|
|
@ -1950,7 +1955,7 @@ void UnloadMesh(Mesh mesh)
|
||||||
// Export mesh data to file
|
// Export mesh data to file
|
||||||
bool ExportMesh(Mesh mesh, const char *fileName)
|
bool ExportMesh(Mesh mesh, const char *fileName)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool result = false;
|
||||||
|
|
||||||
if (IsFileExtension(fileName, ".obj"))
|
if (IsFileExtension(fileName, ".obj"))
|
||||||
{
|
{
|
||||||
|
|
@ -2014,22 +2019,35 @@ bool ExportMesh(Mesh mesh, const char *fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Text data length exported is determined by '\0' (NULL) character
|
// NOTE: Text data length exported is determined by '\0' (NULL) character
|
||||||
success = SaveFileText(fileName, txtData);
|
result = SaveFileText(fileName, txtData);
|
||||||
|
|
||||||
RL_FREE(txtData);
|
RL_FREE(txtData);
|
||||||
}
|
}
|
||||||
|
else if (IsFileExtension(fileName, ".gltf")) // Or .glb
|
||||||
|
{
|
||||||
|
// TODO: Implement gltf/glb support
|
||||||
|
/*
|
||||||
|
cgltf_size expected = cgltf_write(options, NULL, 0, data);
|
||||||
|
char *buffer = (char *)RL_CALLOC(expected, 0);
|
||||||
|
cgltf_size actual = cgltf_write(options, buffer, expected, data);
|
||||||
|
|
||||||
|
// NOTE: cgltf_write() includes a NULL terminator that should be ommited in case of a .glb
|
||||||
|
if (options->type == cgltf_file_type_glb) cgltf_write_glb(file, buffer, actual - 1, data->bin, data->bin_size);
|
||||||
|
else SaveFileText(fileName, buffer); // Write a plain JSON file
|
||||||
|
*/
|
||||||
|
}
|
||||||
else if (IsFileExtension(fileName, ".raw"))
|
else if (IsFileExtension(fileName, ".raw"))
|
||||||
{
|
{
|
||||||
// TODO: Support additional file formats to export mesh vertex data
|
// TODO: Support additional file formats to export mesh vertex data
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export mesh as code file (.h) defining multiple arrays of vertex attributes
|
// Export mesh as code file (.h) defining multiple arrays of vertex attributes
|
||||||
bool ExportMeshAsCode(Mesh mesh, const char *fileName)
|
bool ExportMeshAsCode(Mesh mesh, const char *fileName)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool result = false;
|
||||||
|
|
||||||
#ifndef TEXT_BYTES_PER_LINE
|
#ifndef TEXT_BYTES_PER_LINE
|
||||||
#define TEXT_BYTES_PER_LINE 20
|
#define TEXT_BYTES_PER_LINE 20
|
||||||
|
|
@ -2113,14 +2131,14 @@ bool ExportMeshAsCode(Mesh mesh, const char *fileName)
|
||||||
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
||||||
success = SaveFileText(fileName, txtData);
|
result = SaveFileText(fileName, txtData);
|
||||||
|
|
||||||
RL_FREE(txtData);
|
RL_FREE(txtData);
|
||||||
|
|
||||||
//if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Image as code exported successfully", fileName);
|
//if (result != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Image as code exported successfully", fileName);
|
||||||
//else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export image as code", fileName);
|
//else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export image as code", fileName);
|
||||||
|
|
||||||
return success;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SUPPORT_FILEFORMAT_OBJ || SUPPORT_FILEFORMAT_MTL
|
#if SUPPORT_FILEFORMAT_OBJ || SUPPORT_FILEFORMAT_MTL
|
||||||
|
|
@ -3961,32 +3979,6 @@ void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float
|
||||||
rlDisableWireMode();
|
rlDisableWireMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a model points
|
|
||||||
// WARNING: OpenGL ES 2.0 does not support point mode drawing
|
|
||||||
void DrawModelPoints(Model model, Vector3 position, float scale, Color tint)
|
|
||||||
{
|
|
||||||
rlEnablePointMode();
|
|
||||||
rlDisableBackfaceCulling();
|
|
||||||
|
|
||||||
DrawModel(model, position, scale, tint);
|
|
||||||
|
|
||||||
rlEnableBackfaceCulling();
|
|
||||||
rlDisablePointMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw a model points
|
|
||||||
// WARNING: OpenGL ES 2.0 does not support point mode drawing
|
|
||||||
void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint)
|
|
||||||
{
|
|
||||||
rlEnablePointMode();
|
|
||||||
rlDisableBackfaceCulling();
|
|
||||||
|
|
||||||
DrawModelEx(model, position, rotationAxis, rotationAngle, scale, tint);
|
|
||||||
|
|
||||||
rlEnableBackfaceCulling();
|
|
||||||
rlDisablePointMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw a billboard
|
// Draw a billboard
|
||||||
void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint)
|
void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint)
|
||||||
{
|
{
|
||||||
|
|
@ -5292,7 +5284,7 @@ static cgltf_result LoadFileGLTFCallback(const struct cgltf_memory_options *memo
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release file data callback for cgltf
|
// Release file data callback for cgltf
|
||||||
static void ReleaseFileGLTFCallback(const struct cgltf_memory_options *memoryOptions, const struct cgltf_file_options *fileOptions, void *data)
|
static void ReleaseFileGLTFCallback(const struct cgltf_memory_options *memoryOptions, const struct cgltf_file_options *fileOptions, void *data, cgltf_size size)
|
||||||
{
|
{
|
||||||
UnloadFileData((unsigned char *)data);
|
UnloadFileData((unsigned char *)data);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2348,16 +2348,18 @@ bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec)
|
||||||
float dx = fabsf(center.x - recCenterX);
|
float dx = fabsf(center.x - recCenterX);
|
||||||
float dy = fabsf(center.y - recCenterY);
|
float dy = fabsf(center.y - recCenterY);
|
||||||
|
|
||||||
if (dx > (rec.width/2.0f + radius)) { return false; }
|
if ((dx <= (rec.width/2.0f + radius)) && (dy <= (rec.height/2.0f + radius)))
|
||||||
if (dy > (rec.height/2.0f + radius)) { return false; }
|
{
|
||||||
|
if (dx <= (rec.width/2.0f)) collision = true;
|
||||||
|
else if (dy <= (rec.height/2.0f)) collision = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float cornerDistanceSq = (dx - rec.width/2.0f)*(dx - rec.width/2.0f) +
|
||||||
|
(dy - rec.height/2.0f)*(dy - rec.height/2.0f);
|
||||||
|
|
||||||
if (dx <= (rec.width/2.0f)) { return true; }
|
collision = (cornerDistanceSq <= (radius*radius));
|
||||||
if (dy <= (rec.height/2.0f)) { return true; }
|
}
|
||||||
|
}
|
||||||
float cornerDistanceSq = (dx - rec.width/2.0f)*(dx - rec.width/2.0f) +
|
|
||||||
(dy - rec.height/2.0f)*(dy - rec.height/2.0f);
|
|
||||||
|
|
||||||
collision = (cornerDistanceSq <= (radius*radius));
|
|
||||||
|
|
||||||
return collision;
|
return collision;
|
||||||
}
|
}
|
||||||
|
|
@ -2418,25 +2420,31 @@ bool CheckCollisionPointLine(Vector2 point, Vector2 p1, Vector2 p2, int threshol
|
||||||
// Check if circle collides with a line created between two points [p1] and [p2]
|
// Check if circle collides with a line created between two points [p1] and [p2]
|
||||||
bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2 p2)
|
bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2 p2)
|
||||||
{
|
{
|
||||||
|
bool collision = false;
|
||||||
|
|
||||||
float dx = p1.x - p2.x;
|
float dx = p1.x - p2.x;
|
||||||
float dy = p1.y - p2.y;
|
float dy = p1.y - p2.y;
|
||||||
|
|
||||||
if ((fabsf(dx) + fabsf(dy)) <= FLT_EPSILON)
|
if ((fabsf(dx) + fabsf(dy)) <= FLT_EPSILON)
|
||||||
{
|
{
|
||||||
return CheckCollisionCircles(p1, 0, center, radius);
|
collision = CheckCollisionCircles(p1, 0, center, radius);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float lengthSQ = ((dx*dx) + (dy*dy));
|
||||||
|
float dotProduct = (((center.x - p1.x)*(p2.x - p1.x)) + ((center.y - p1.y)*(p2.y - p1.y)))/(lengthSQ);
|
||||||
|
|
||||||
|
if (dotProduct > 1.0f) dotProduct = 1.0f;
|
||||||
|
else if (dotProduct < 0.0f) dotProduct = 0.0f;
|
||||||
|
|
||||||
|
float dx2 = (p1.x - (dotProduct*(dx))) - center.x;
|
||||||
|
float dy2 = (p1.y - (dotProduct*(dy))) - center.y;
|
||||||
|
float distanceSQ = ((dx2*dx2) + (dy2*dy2));
|
||||||
|
|
||||||
|
if (distanceSQ <= radius*radius) collision = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
float lengthSQ = ((dx*dx) + (dy*dy));
|
return collision;
|
||||||
float dotProduct = (((center.x - p1.x)*(p2.x - p1.x)) + ((center.y - p1.y)*(p2.y - p1.y)))/(lengthSQ);
|
|
||||||
|
|
||||||
if (dotProduct > 1.0f) dotProduct = 1.0f;
|
|
||||||
else if (dotProduct < 0.0f) dotProduct = 0.0f;
|
|
||||||
|
|
||||||
float dx2 = (p1.x - (dotProduct*(dx))) - center.x;
|
|
||||||
float dy2 = (p1.y - (dotProduct*(dy))) - center.y;
|
|
||||||
float distanceSQ = ((dx2*dx2) + (dy2*dy2));
|
|
||||||
|
|
||||||
return (distanceSQ <= radius*radius);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get collision rectangle for two rectangles collision
|
// Get collision rectangle for two rectangles collision
|
||||||
|
|
|
||||||
169
src/rtext.c
169
src/rtext.c
|
|
@ -447,7 +447,7 @@ Font LoadFontFromImage(Image image, Color key, int firstChar)
|
||||||
int j = 0;
|
int j = 0;
|
||||||
|
|
||||||
while (((lineSpacing + j) < image.height) &&
|
while (((lineSpacing + j) < image.height) &&
|
||||||
!COLOR_EQUAL(pixels[(lineSpacing + j)*image.width + charSpacing], key)) j++;
|
!COLOR_EQUAL(pixels[(lineSpacing + j)*image.width + charSpacing], key)) j++;
|
||||||
|
|
||||||
charHeight = j;
|
charHeight = j;
|
||||||
|
|
||||||
|
|
@ -1017,7 +1017,7 @@ void UnloadFont(Font font)
|
||||||
// Export font as code file, returns true on success
|
// Export font as code file, returns true on success
|
||||||
bool ExportFontAsCode(Font font, const char *fileName)
|
bool ExportFontAsCode(Font font, const char *fileName)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool result = false;
|
||||||
|
|
||||||
#ifndef TEXT_BYTES_PER_LINE
|
#ifndef TEXT_BYTES_PER_LINE
|
||||||
#define TEXT_BYTES_PER_LINE 20
|
#define TEXT_BYTES_PER_LINE 20
|
||||||
|
|
@ -1159,14 +1159,14 @@ bool ExportFontAsCode(Font font, const char *fileName)
|
||||||
UnloadImage(image);
|
UnloadImage(image);
|
||||||
|
|
||||||
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
||||||
success = SaveFileText(fileName, txtData);
|
result = SaveFileText(fileName, txtData);
|
||||||
|
|
||||||
RL_FREE(txtData);
|
RL_FREE(txtData);
|
||||||
|
|
||||||
if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Font as code exported successfully", fileName);
|
if (result != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Font as code exported successfully", fileName);
|
||||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export font as code", fileName);
|
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export font as code", fileName);
|
||||||
|
|
||||||
return success;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw current FPS
|
// Draw current FPS
|
||||||
|
|
@ -1395,8 +1395,7 @@ Vector2 MeasureTextCodepoints(Font font, const int *codepoints, int length, floa
|
||||||
{
|
{
|
||||||
Vector2 textSize = { 0 };
|
Vector2 textSize = { 0 };
|
||||||
|
|
||||||
// Security check
|
if ((font.texture.id == 0) || (codepoints == NULL) || (length == 0)) return textSize; // Security check
|
||||||
if ((font.texture.id == 0) || (codepoints == NULL) || (length == 0)) return textSize;
|
|
||||||
|
|
||||||
float textWidth = 0.0f;
|
float textWidth = 0.0f;
|
||||||
// Used to count longer text line width
|
// Used to count longer text line width
|
||||||
|
|
@ -1699,17 +1698,18 @@ const char *TextSubtext(const char *text, int position, int length)
|
||||||
{
|
{
|
||||||
int textLength = TextLength(text);
|
int textLength = TextLength(text);
|
||||||
|
|
||||||
if (position >= textLength) return buffer; // First char is already '\0' by memset
|
if (position < textLength)
|
||||||
|
{
|
||||||
|
int maxLength = textLength - position;
|
||||||
|
if (length > maxLength) length = maxLength;
|
||||||
|
if (length >= MAX_TEXT_BUFFER_LENGTH) length = MAX_TEXT_BUFFER_LENGTH - 1;
|
||||||
|
|
||||||
int maxLength = textLength - position;
|
// NOTE: Alternative: memcpy(buffer, text + position, length)
|
||||||
if (length > maxLength) length = maxLength;
|
|
||||||
if (length >= MAX_TEXT_BUFFER_LENGTH) length = MAX_TEXT_BUFFER_LENGTH - 1;
|
|
||||||
|
|
||||||
// NOTE: Alternative: memcpy(buffer, text + position, length)
|
for (int c = 0; c < length; c++) buffer[c] = text[position + c];
|
||||||
|
|
||||||
for (int c = 0; c < length; c++) buffer[c] = text[position + c];
|
buffer[length] = '\0';
|
||||||
|
}
|
||||||
buffer[length] = '\0';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
|
|
@ -1736,8 +1736,6 @@ const char *TextRemoveSpaces(const char *text)
|
||||||
// Get text between two strings
|
// Get text between two strings
|
||||||
char *GetTextBetween(const char *text, const char *begin, const char *end)
|
char *GetTextBetween(const char *text, const char *begin, const char *end)
|
||||||
{
|
{
|
||||||
#define MAX_TEXT_BETWEEN_SIZE 1024
|
|
||||||
|
|
||||||
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||||
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||||
|
|
||||||
|
|
@ -1752,8 +1750,8 @@ char *GetTextBetween(const char *text, const char *begin, const char *end)
|
||||||
{
|
{
|
||||||
endIndex += (beginIndex + beginLen);
|
endIndex += (beginIndex + beginLen);
|
||||||
int len = (endIndex - beginIndex - beginLen);
|
int len = (endIndex - beginIndex - beginLen);
|
||||||
if (len < (MAX_TEXT_BETWEEN_SIZE - 1)) strncpy(buffer, text + beginIndex + beginLen, len);
|
if (len < (MAX_TEXT_BUFFER_LENGTH - 1)) strncpy(buffer, text + beginIndex + beginLen, len);
|
||||||
else strncpy(buffer, text + beginIndex + beginLen, MAX_TEXT_BETWEEN_SIZE - 1);
|
else strncpy(buffer, text + beginIndex + beginLen, MAX_TEXT_BUFFER_LENGTH - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1762,8 +1760,74 @@ char *GetTextBetween(const char *text, const char *begin, const char *end)
|
||||||
|
|
||||||
// Replace text string
|
// Replace text string
|
||||||
// REQUIRES: strstr(), strncpy()
|
// REQUIRES: strstr(), strncpy()
|
||||||
// WARNING: Allocated memory must be manually freed
|
// NOTE: Limited text replace functionality, using static string
|
||||||
char *TextReplace(const char *text, const char *search, const char *replacement)
|
char *TextReplace(const char *text, const char *search, const char *replacement)
|
||||||
|
{
|
||||||
|
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||||
|
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||||
|
|
||||||
|
if ((text != NULL) && (search != NULL) && (search[0] != '\0'))
|
||||||
|
{
|
||||||
|
if (replacement == NULL) replacement = "";
|
||||||
|
|
||||||
|
char *insertPoint = NULL; // Next insert point
|
||||||
|
char *tempPtr = NULL; // Temp pointer
|
||||||
|
int textLen = 0; // Text string length
|
||||||
|
int searchLen = 0; // Search string length of (the string to remove)
|
||||||
|
int replaceLen = 0; // Replacement length (the string to replace by)
|
||||||
|
int lastReplacePos = 0; // Distance between next search and end of last replace
|
||||||
|
int count = 0; // Number of replacements
|
||||||
|
|
||||||
|
textLen = TextLength(text);
|
||||||
|
searchLen = TextLength(search);
|
||||||
|
replaceLen = TextLength(replacement);
|
||||||
|
|
||||||
|
// Count the number of replacements needed
|
||||||
|
insertPoint = (char *)text;
|
||||||
|
for (count = 0; (tempPtr = strstr(insertPoint, search)); count++) insertPoint = tempPtr + searchLen;
|
||||||
|
|
||||||
|
if ((textLen + count*(replaceLen - searchLen)) < (MAX_TEXT_BUFFER_LENGTH - 1))
|
||||||
|
{
|
||||||
|
// TODO: Allow copying data replaced up to maximum buffer size and stop
|
||||||
|
|
||||||
|
tempPtr = buffer; // Point to result start
|
||||||
|
|
||||||
|
// First time through the loop, all the variable are set correctly from here on,
|
||||||
|
// - 'temp' points to the end of the result string
|
||||||
|
// - 'insertPoint' points to the next occurrence of replace in text
|
||||||
|
// - 'text' points to the remainder of text after "end of replace"
|
||||||
|
while (count > 0)
|
||||||
|
{
|
||||||
|
insertPoint = (char *)strstr(text, search);
|
||||||
|
lastReplacePos = (int)(insertPoint - text);
|
||||||
|
|
||||||
|
memcpy(tempPtr, text, lastReplacePos);
|
||||||
|
tempPtr += lastReplacePos;
|
||||||
|
|
||||||
|
if (replaceLen > 0)
|
||||||
|
{
|
||||||
|
memcpy(tempPtr, replacement, replaceLen);
|
||||||
|
tempPtr += replaceLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
text += (lastReplacePos + searchLen); // Move to next "end of replace"
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy remaind text part after replacement to result (pointed by moving temp)
|
||||||
|
// NOTE: Text pointer internal copy has been updated along the process
|
||||||
|
strncpy(tempPtr, text, TextLength(text));
|
||||||
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "Text with replacement is longer than internal buffer, use TextReplaceAlloc()");
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace text string
|
||||||
|
// REQUIRES: strstr(), strncpy()
|
||||||
|
// WARNING: Allocated memory must be manually freed
|
||||||
|
char *TextReplaceAlloc(const char *text, const char *search, const char *replacement)
|
||||||
{
|
{
|
||||||
char *result = NULL;
|
char *result = NULL;
|
||||||
|
|
||||||
|
|
@ -1825,11 +1889,46 @@ char *TextReplace(const char *text, const char *search, const char *replacement)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Replace text between two specific strings
|
||||||
|
// REQUIRES: strncpy()
|
||||||
|
// NOTE: If (replacement == NULL) removes "begin"[ ]"end" text
|
||||||
|
char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replacement)
|
||||||
|
{
|
||||||
|
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||||
|
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||||
|
|
||||||
|
if ((text != NULL) && (begin != NULL) && (end != NULL))
|
||||||
|
{
|
||||||
|
int beginIndex = TextFindIndex(text, begin);
|
||||||
|
|
||||||
|
if (beginIndex > -1)
|
||||||
|
{
|
||||||
|
int beginLen = TextLength(begin);
|
||||||
|
int endIndex = TextFindIndex(text + beginIndex + beginLen, end);
|
||||||
|
|
||||||
|
if (endIndex > -1)
|
||||||
|
{
|
||||||
|
endIndex += (beginIndex + beginLen);
|
||||||
|
|
||||||
|
int textLen = TextLength(text);
|
||||||
|
int replaceLen = (replacement == NULL)? 0 : TextLength(replacement);
|
||||||
|
//int toreplaceLen = endIndex - beginIndex - beginLen;
|
||||||
|
|
||||||
|
strncpy(buffer, text, beginIndex + beginLen); // Copy first text part
|
||||||
|
if (replacement != NULL) strncpy(buffer + beginIndex + beginLen, replacement, replaceLen); // Copy replacement (if provided)
|
||||||
|
strncpy(buffer + beginIndex + beginLen + replaceLen, text + endIndex, textLen - endIndex); // Copy end text part
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
// Replace text between two specific strings
|
// Replace text between two specific strings
|
||||||
// REQUIRES: strncpy()
|
// REQUIRES: strncpy()
|
||||||
// NOTE: If (replacement == NULL) remove "begin"[ ]"end" text
|
// NOTE: If (replacement == NULL) remove "begin"[ ]"end" text
|
||||||
// WARNING: Returned string must be freed by user
|
// WARNING: Returned string must be freed by user
|
||||||
char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replacement)
|
char *TextReplaceBetweenAlloc(const char *text, const char *begin, const char *end, const char *replacement)
|
||||||
{
|
{
|
||||||
char *result = NULL;
|
char *result = NULL;
|
||||||
|
|
||||||
|
|
@ -1864,6 +1963,34 @@ char *TextReplaceBetween(const char *text, const char *begin, const char *end, c
|
||||||
// Insert text in a specific position, moves all text forward
|
// Insert text in a specific position, moves all text forward
|
||||||
// WARNING: Allocated memory must be manually freed
|
// WARNING: Allocated memory must be manually freed
|
||||||
char *TextInsert(const char *text, const char *insert, int position)
|
char *TextInsert(const char *text, const char *insert, int position)
|
||||||
|
{
|
||||||
|
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||||
|
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||||
|
|
||||||
|
if ((text != NULL) && (insert != NULL))
|
||||||
|
{
|
||||||
|
int textLen = TextLength(text);
|
||||||
|
int insertLen = TextLength(insert);
|
||||||
|
|
||||||
|
if ((textLen + insertLen) < (MAX_TEXT_BUFFER_LENGTH - 1))
|
||||||
|
{
|
||||||
|
// TODO: Allow copying data inserted up to maximum buffer size and stop
|
||||||
|
|
||||||
|
for (int i = 0; i < position; i++) buffer[i] = text[i];
|
||||||
|
for (int i = position; i < insertLen + position; i++) buffer[i] = insert[i - position];
|
||||||
|
for (int i = (insertLen + position); i < (textLen + insertLen); i++) buffer[i] = text[i];
|
||||||
|
|
||||||
|
buffer[textLen + insertLen] = '\0'; // Add EOL
|
||||||
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "Text with inserted string is longer than internal buffer, use TextInserExt()");
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert text in a specific position, moves all text forward
|
||||||
|
// WARNING: Allocated memory must be manually freed
|
||||||
|
char *TextInsertAlloc(const char *text, const char *insert, int position)
|
||||||
{
|
{
|
||||||
char *result = NULL;
|
char *result = NULL;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -376,8 +376,7 @@ Image LoadImageAnimFromMemory(const char *fileType, const unsigned char *fileDat
|
||||||
Image image = { 0 };
|
Image image = { 0 };
|
||||||
int frameCount = 0;
|
int frameCount = 0;
|
||||||
|
|
||||||
// Security check for input data
|
if ((fileType == NULL) || (fileData == NULL) || (dataSize == 0)) return image; // Security check
|
||||||
if ((fileType == NULL) || (fileData == NULL) || (dataSize == 0)) return image;
|
|
||||||
|
|
||||||
#if SUPPORT_FILEFORMAT_GIF
|
#if SUPPORT_FILEFORMAT_GIF
|
||||||
if ((strcmp(fileType, ".gif") == 0) || (strcmp(fileType, ".GIF") == 0))
|
if ((strcmp(fileType, ".gif") == 0) || (strcmp(fileType, ".GIF") == 0))
|
||||||
|
|
@ -621,8 +620,7 @@ bool ExportImage(Image image, const char *fileName)
|
||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
// Security check for input data
|
if ((image.width == 0) || (image.height == 0) || (image.data == NULL)) return result; // Security check
|
||||||
if ((image.width == 0) || (image.height == 0) || (image.data == NULL)) return result;
|
|
||||||
|
|
||||||
#if SUPPORT_IMAGE_EXPORT
|
#if SUPPORT_IMAGE_EXPORT
|
||||||
int channels = 4;
|
int channels = 4;
|
||||||
|
|
@ -709,8 +707,7 @@ unsigned char *ExportImageToMemory(Image image, const char *fileType, int *dataS
|
||||||
unsigned char *fileData = NULL;
|
unsigned char *fileData = NULL;
|
||||||
*dataSize = 0;
|
*dataSize = 0;
|
||||||
|
|
||||||
// Security check for input data
|
if ((image.width == 0) || (image.height == 0) || (image.data == NULL)) return fileData; // Security check
|
||||||
if ((image.width == 0) || (image.height == 0) || (image.data == NULL)) return NULL;
|
|
||||||
|
|
||||||
int channels = 4;
|
int channels = 4;
|
||||||
|
|
||||||
|
|
@ -734,7 +731,7 @@ unsigned char *ExportImageToMemory(Image image, const char *fileType, int *dataS
|
||||||
// Export image as code file (.h) defining an array of bytes
|
// Export image as code file (.h) defining an array of bytes
|
||||||
bool ExportImageAsCode(Image image, const char *fileName)
|
bool ExportImageAsCode(Image image, const char *fileName)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool result = false;
|
||||||
|
|
||||||
#ifndef TEXT_BYTES_PER_LINE
|
#ifndef TEXT_BYTES_PER_LINE
|
||||||
#define TEXT_BYTES_PER_LINE 20
|
#define TEXT_BYTES_PER_LINE 20
|
||||||
|
|
@ -774,14 +771,14 @@ bool ExportImageAsCode(Image image, const char *fileName)
|
||||||
byteCount += sprintf(txtData + byteCount, "0x%x };\n", ((unsigned char *)image.data)[dataSize - 1]);
|
byteCount += sprintf(txtData + byteCount, "0x%x };\n", ((unsigned char *)image.data)[dataSize - 1]);
|
||||||
|
|
||||||
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
||||||
success = SaveFileText(fileName, txtData);
|
result = SaveFileText(fileName, txtData);
|
||||||
|
|
||||||
RL_FREE(txtData);
|
RL_FREE(txtData);
|
||||||
|
|
||||||
if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Image as code exported successfully", fileName);
|
if (result != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Image as code exported successfully", fileName);
|
||||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export image as code", fileName);
|
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export image as code", fileName);
|
||||||
|
|
||||||
return success;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
|
|
@ -1536,8 +1533,7 @@ Image ImageFromChannel(Image image, int selectedChannel)
|
||||||
{
|
{
|
||||||
Image result = { 0 };
|
Image result = { 0 };
|
||||||
|
|
||||||
// Security check to avoid program crash
|
if ((image.data == NULL) || (image.width == 0) || (image.height == 0)) return result; // Security check
|
||||||
if ((image.data == NULL) || (image.width == 0) || (image.height == 0)) return result;
|
|
||||||
|
|
||||||
// Check selected channel is valid
|
// Check selected channel is valid
|
||||||
if (selectedChannel < 0)
|
if (selectedChannel < 0)
|
||||||
|
|
@ -2937,7 +2933,7 @@ void ImageColorReplace(Image *image, Color color, Color replace)
|
||||||
// NOTE: Memory allocated should be freed using UnloadImageColors();
|
// NOTE: Memory allocated should be freed using UnloadImageColors();
|
||||||
Color *LoadImageColors(Image image)
|
Color *LoadImageColors(Image image)
|
||||||
{
|
{
|
||||||
if ((image.width == 0) || (image.height == 0)) return NULL;
|
if ((image.width == 0) || (image.height == 0)) return NULL; // Security check
|
||||||
|
|
||||||
Color *pixels = (Color *)RL_MALLOC(image.width*image.height*sizeof(Color));
|
Color *pixels = (Color *)RL_MALLOC(image.width*image.height*sizeof(Color));
|
||||||
|
|
||||||
|
|
@ -4903,44 +4899,44 @@ Vector3 ColorToHSV(Color color)
|
||||||
float max = 0.0f;
|
float max = 0.0f;
|
||||||
float delta = 0.0f;
|
float delta = 0.0f;
|
||||||
|
|
||||||
min = rgb.x < rgb.y? rgb.x : rgb.y;
|
min = (rgb.x < rgb.y)? rgb.x : rgb.y;
|
||||||
min = min < rgb.z? min : rgb.z;
|
min = (min < rgb.z)? min : rgb.z;
|
||||||
|
|
||||||
max = rgb.x > rgb.y? rgb.x : rgb.y;
|
max = (rgb.x > rgb.y)? rgb.x : rgb.y;
|
||||||
max = max > rgb.z? max : rgb.z;
|
max = (max > rgb.z)? max : rgb.z;
|
||||||
|
|
||||||
hsv.z = max; // Value
|
hsv.z = max; // Value
|
||||||
delta = max - min;
|
delta = max - min;
|
||||||
|
|
||||||
if (delta < 0.00001f)
|
if (delta < 0.00001f)
|
||||||
{
|
{
|
||||||
hsv.y = 0.0f;
|
hsv.y = 0.0f;
|
||||||
hsv.x = 0.0f; // Undefined, maybe NAN?
|
hsv.x = 0.0f; // Undefined, maybe NAN?
|
||||||
return hsv;
|
return hsv;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (max > 0.0f)
|
if (max > 0.0f)
|
||||||
{
|
{
|
||||||
// NOTE: If max is 0, this divide would cause a crash
|
// NOTE: If max is 0, this divide would cause a crash
|
||||||
hsv.y = (delta/max); // Saturation
|
hsv.y = (delta/max); // Saturation
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// NOTE: If max is 0, then r = g = b = 0, s = 0, h is undefined
|
// NOTE: If max is 0, then r = g = b = 0, s = 0, h is undefined
|
||||||
hsv.y = 0.0f;
|
hsv.y = 0.0f;
|
||||||
hsv.x = NAN; // Undefined
|
hsv.x = NAN; // Undefined
|
||||||
return hsv;
|
return hsv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Comparing float values could not work properly
|
// NOTE: Comparing float values could not work properly
|
||||||
if (rgb.x >= max) hsv.x = (rgb.y - rgb.z)/delta; // Between yellow & magenta
|
if (rgb.x >= max) hsv.x = (rgb.y - rgb.z)/delta; // Between yellow & magenta
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (rgb.y >= max) hsv.x = 2.0f + (rgb.z - rgb.x)/delta; // Between cyan & yellow
|
if (rgb.y >= max) hsv.x = 2.0f + (rgb.z - rgb.x)/delta; // Between cyan & yellow
|
||||||
else hsv.x = 4.0f + (rgb.x - rgb.y)/delta; // Between magenta & cyan
|
else hsv.x = 4.0f + (rgb.x - rgb.y)/delta; // Between magenta & cyan
|
||||||
}
|
}
|
||||||
|
|
||||||
hsv.x *= 60.0f; // Convert to degrees
|
hsv.x *= 60.0f; // Convert to degrees
|
||||||
|
|
||||||
if (hsv.x < 0.0f) hsv.x += 360.0f;
|
if (hsv.x < 0.0f) hsv.x += 360.0f;
|
||||||
|
|
||||||
|
|
@ -5093,7 +5089,7 @@ Color ColorAlpha(Color color, float alpha)
|
||||||
// Get src alpha-blended into dst color with tint
|
// Get src alpha-blended into dst color with tint
|
||||||
Color ColorAlphaBlend(Color dst, Color src, Color tint)
|
Color ColorAlphaBlend(Color dst, Color src, Color tint)
|
||||||
{
|
{
|
||||||
Color out = WHITE;
|
Color result = WHITE;
|
||||||
|
|
||||||
// Apply color tint to source color
|
// Apply color tint to source color
|
||||||
src.r = (unsigned char)(((unsigned int)src.r*((unsigned int)tint.r+1)) >> 8);
|
src.r = (unsigned char)(((unsigned int)src.r*((unsigned int)tint.r+1)) >> 8);
|
||||||
|
|
@ -5104,24 +5100,24 @@ Color ColorAlphaBlend(Color dst, Color src, Color tint)
|
||||||
//#define COLORALPHABLEND_FLOAT
|
//#define COLORALPHABLEND_FLOAT
|
||||||
#define COLORALPHABLEND_INTEGERS
|
#define COLORALPHABLEND_INTEGERS
|
||||||
#if defined(COLORALPHABLEND_INTEGERS)
|
#if defined(COLORALPHABLEND_INTEGERS)
|
||||||
if (src.a == 0) out = dst;
|
if (src.a == 0) result = dst;
|
||||||
else if (src.a == 255) out = src;
|
else if (src.a == 255) result = src;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned int alpha = (unsigned int)src.a + 1; // Shifting by 8 (dividing by 256), so need to take that excess into account
|
unsigned int alpha = (unsigned int)src.a + 1; // Shifting by 8 (dividing by 256), so need to take that excess into account
|
||||||
out.a = (unsigned char)(((unsigned int)alpha*256 + (unsigned int)dst.a*(256 - alpha)) >> 8);
|
result.a = (unsigned char)(((unsigned int)alpha*256 + (unsigned int)dst.a*(256 - alpha)) >> 8);
|
||||||
|
|
||||||
if (out.a > 0)
|
if (result.a > 0)
|
||||||
{
|
{
|
||||||
out.r = (unsigned char)((((unsigned int)src.r*alpha*256 + (unsigned int)dst.r*(unsigned int)dst.a*(256 - alpha))/out.a) >> 8);
|
result.r = (unsigned char)((((unsigned int)src.r*alpha*256 + (unsigned int)dst.r*(unsigned int)dst.a*(256 - alpha))/result.a) >> 8);
|
||||||
out.g = (unsigned char)((((unsigned int)src.g*alpha*256 + (unsigned int)dst.g*(unsigned int)dst.a*(256 - alpha))/out.a) >> 8);
|
result.g = (unsigned char)((((unsigned int)src.g*alpha*256 + (unsigned int)dst.g*(unsigned int)dst.a*(256 - alpha))/result.a) >> 8);
|
||||||
out.b = (unsigned char)((((unsigned int)src.b*alpha*256 + (unsigned int)dst.b*(unsigned int)dst.a*(256 - alpha))/out.a) >> 8);
|
result.b = (unsigned char)((((unsigned int)src.b*alpha*256 + (unsigned int)dst.b*(unsigned int)dst.a*(256 - alpha))/result.a) >> 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(COLORALPHABLEND_FLOAT)
|
#if defined(COLORALPHABLEND_FLOAT)
|
||||||
if (src.a == 0) out = dst;
|
if (src.a == 0) result = dst;
|
||||||
else if (src.a == 255) out = src;
|
else if (src.a == 255) result = src;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Vector4 fdst = ColorNormalize(dst);
|
Vector4 fdst = ColorNormalize(dst);
|
||||||
|
|
@ -5138,11 +5134,11 @@ Color ColorAlphaBlend(Color dst, Color src, Color tint)
|
||||||
fout.z = (fsrc.z*fsrc.w + fdst.z*fdst.w*(1 - fsrc.w))/fout.w;
|
fout.z = (fsrc.z*fsrc.w + fdst.z*fdst.w*(1 - fsrc.w))/fout.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
out = (Color){ (unsigned char)(fout.x*255.0f), (unsigned char)(fout.y*255.0f), (unsigned char)(fout.z*255.0f), (unsigned char)(fout.w*255.0f) };
|
result = (Color){ (unsigned char)(fout.x*255.0f), (unsigned char)(fout.y*255.0f), (unsigned char)(fout.z*255.0f), (unsigned char)(fout.w*255.0f) };
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return out;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get color lerp interpolation between two colors, factor [0.0f..1.0f]
|
// Get color lerp interpolation between two colors, factor [0.0f..1.0f]
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@
|
||||||
#define REXM_MAX_BUFFER_SIZE (2*1024*1024) // 2MB
|
#define REXM_MAX_BUFFER_SIZE (2*1024*1024) // 2MB
|
||||||
|
|
||||||
#define REXM_MAX_RESOURCE_PATHS 256
|
#define REXM_MAX_RESOURCE_PATHS 256
|
||||||
|
#define REXM_MAX_RESOURCE_PATH_LENGTH 256
|
||||||
|
|
||||||
// Create local commit with changes on example renaming
|
// Create local commit with changes on example renaming
|
||||||
//#define RENAME_AUTO_COMMIT_CREATION
|
//#define RENAME_AUTO_COMMIT_CREATION
|
||||||
|
|
@ -469,12 +470,12 @@ int main(int argc, char *argv[])
|
||||||
int exIndex = TextFindIndex(exText, "/****************");
|
int exIndex = TextFindIndex(exText, "/****************");
|
||||||
|
|
||||||
// Update required info with some defaults
|
// Update required info with some defaults
|
||||||
exTextUpdated[0] = TextReplace(exText + exIndex, "<module>", exCategory);
|
exTextUpdated[0] = TextReplaceAlloc(exText + exIndex, "<module>", exCategory);
|
||||||
exTextUpdated[1] = TextReplace(exTextUpdated[0], "<name>", exName + strlen(exCategory) + 1);
|
exTextUpdated[1] = TextReplaceAlloc(exTextUpdated[0], "<name>", exName + strlen(exCategory) + 1);
|
||||||
//TextReplace(newExample, "<user_name>", "Ray");
|
//TextReplaceAlloc(newExample, "<user_name>", "Ray");
|
||||||
//TextReplace(newExample, "@<user_github>", "@raysan5");
|
//TextReplaceAlloc(newExample, "@<user_github>", "@raysan5");
|
||||||
//TextReplace(newExample, "<year_created>", 2025);
|
//TextReplaceAlloc(newExample, "<year_created>", 2025);
|
||||||
//TextReplace(newExample, "<year_updated>", 2025);
|
//TextReplaceAlloc(newExample, "<year_updated>", 2025);
|
||||||
|
|
||||||
SaveFileText(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName), exTextUpdated[1]);
|
SaveFileText(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName), exTextUpdated[1]);
|
||||||
for (int i = 0; i < 6; i++) { MemFree(exTextUpdated[i]); exTextUpdated[i] = NULL; }
|
for (int i = 0; i < 6; i++) { MemFree(exTextUpdated[i]); exTextUpdated[i] = NULL; }
|
||||||
|
|
@ -541,8 +542,6 @@ int main(int argc, char *argv[])
|
||||||
else LOG("WARNING: Example resource must be placed in 'resources' directory next to .c file\n");
|
else LOG("WARNING: Example resource must be placed in 'resources' directory next to .c file\n");
|
||||||
}
|
}
|
||||||
else LOG("WARNING: Example resource can not be found in: %s\n", TextFormat("%s/%s", GetDirectoryPath(inFileName), resPathUpdated));
|
else LOG("WARNING: Example resource can not be found in: %s\n", TextFormat("%s/%s", GetDirectoryPath(inFileName), resPathUpdated));
|
||||||
|
|
||||||
RL_FREE(resPathUpdated);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -863,9 +862,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
for (int v = 0; v < 3; v++)
|
for (int v = 0; v < 3; v++)
|
||||||
{
|
{
|
||||||
char *resPathUpdated = TextReplace(resPaths[r], "glsl%i", TextFormat("glsl%i", glslVer[v]));
|
FileRemove(TextFormat("%s/%s/%s", exBasePath, exCategory, TextReplace(resPaths[r], "glsl%i", TextFormat("glsl%i", glslVer[v]))));
|
||||||
FileRemove(TextFormat("%s/%s/%s", exBasePath, exCategory, resPathUpdated));
|
|
||||||
RL_FREE(resPathUpdated);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else FileRemove(TextFormat("%s/%s/%s", exBasePath, exCategory, resPaths[r]));
|
else FileRemove(TextFormat("%s/%s/%s", exBasePath, exCategory, resPaths[r]));
|
||||||
|
|
@ -1164,7 +1161,6 @@ int main(int argc, char *argv[])
|
||||||
// Logging missing resources for convenience
|
// Logging missing resources for convenience
|
||||||
LOG("WARNING: [%s] Missing resource: %s\n", exInfo->name, resPathUpdated);
|
LOG("WARNING: [%s] Missing resource: %s\n", exInfo->name, resPathUpdated);
|
||||||
}
|
}
|
||||||
RL_FREE(resPathUpdated);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1577,13 +1573,13 @@ int main(int argc, char *argv[])
|
||||||
" SaveFileText(\"outputLogFileName\", logText);\n"
|
" SaveFileText(\"outputLogFileName\", logText);\n"
|
||||||
" emscripten_run_script(\"saveFileFromMEMFSToDisk('outputLogFileName','outputLogFileName')\");\n\n"
|
" emscripten_run_script(\"saveFileFromMEMFSToDisk('outputLogFileName','outputLogFileName')\");\n\n"
|
||||||
" return 0";
|
" return 0";
|
||||||
char *returnReplaceTextUpdated = TextReplace(returnReplaceText, "outputLogFileName", TextFormat("%s.log", exName));
|
char *returnReplaceTextUpdated = TextReplaceAlloc(returnReplaceText, "outputLogFileName", TextFormat("%s.log", exName));
|
||||||
|
|
||||||
char *srcTextUpdated[4] = { 0 };
|
char *srcTextUpdated[4] = { 0 };
|
||||||
srcTextUpdated[0] = TextReplace(srcText, "int main(void)\n{", mainReplaceText);
|
srcTextUpdated[0] = TextReplaceAlloc(srcText, "int main(void)\n{", mainReplaceText);
|
||||||
srcTextUpdated[1] = TextReplace(srcTextUpdated[0], "WindowShouldClose()", "WindowShouldClose() && (testFramesCount < requestedTestFrames)");
|
srcTextUpdated[1] = TextReplaceAlloc(srcTextUpdated[0], "WindowShouldClose()", "WindowShouldClose() && (testFramesCount < requestedTestFrames)");
|
||||||
srcTextUpdated[2] = TextReplace(srcTextUpdated[1], "EndDrawing();", "EndDrawing(); testFramesCount++;");
|
srcTextUpdated[2] = TextReplaceAlloc(srcTextUpdated[1], "EndDrawing();", "EndDrawing(); testFramesCount++;");
|
||||||
srcTextUpdated[3] = TextReplace(srcTextUpdated[2], " return 0", returnReplaceTextUpdated);
|
srcTextUpdated[3] = TextReplaceAlloc(srcTextUpdated[2], " return 0", returnReplaceTextUpdated);
|
||||||
MemFree(returnReplaceTextUpdated);
|
MemFree(returnReplaceTextUpdated);
|
||||||
UnloadFileText(srcText);
|
UnloadFileText(srcText);
|
||||||
|
|
||||||
|
|
@ -1633,9 +1629,9 @@ int main(int argc, char *argv[])
|
||||||
" if ((argc > 1) && (argc == 3) && (strcmp(argv[1], \"--frames\") != 0)) requestedTestFrames = atoi(argv[2]);\n";
|
" if ((argc > 1) && (argc == 3) && (strcmp(argv[1], \"--frames\") != 0)) requestedTestFrames = atoi(argv[2]);\n";
|
||||||
|
|
||||||
char *srcTextUpdated[3] = { 0 };
|
char *srcTextUpdated[3] = { 0 };
|
||||||
srcTextUpdated[0] = TextReplace(srcText, "int main(void)\n{", mainReplaceText);
|
srcTextUpdated[0] = TextReplaceAlloc(srcText, "int main(void)\n{", mainReplaceText);
|
||||||
srcTextUpdated[1] = TextReplace(srcTextUpdated[0], "WindowShouldClose()", "WindowShouldClose() && (testFramesCount < requestedTestFrames)");
|
srcTextUpdated[1] = TextReplaceAlloc(srcTextUpdated[0], "WindowShouldClose()", "WindowShouldClose() && (testFramesCount < requestedTestFrames)");
|
||||||
srcTextUpdated[2] = TextReplace(srcTextUpdated[1], "EndDrawing();", "EndDrawing(); testFramesCount++;");
|
srcTextUpdated[2] = TextReplaceAlloc(srcTextUpdated[1], "EndDrawing();", "EndDrawing(); testFramesCount++;");
|
||||||
UnloadFileText(srcText);
|
UnloadFileText(srcText);
|
||||||
|
|
||||||
SaveFileText(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName), srcTextUpdated[2]);
|
SaveFileText(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName), srcTextUpdated[2]);
|
||||||
|
|
@ -2042,7 +2038,7 @@ static int UpdateRequiredFiles(void)
|
||||||
// In this case, we focus on web building for: glsl100
|
// In this case, we focus on web building for: glsl100
|
||||||
if (TextFindIndex(resPaths[r], "glsl%i") > -1)
|
if (TextFindIndex(resPaths[r], "glsl%i") > -1)
|
||||||
{
|
{
|
||||||
char *resPathUpdated = TextReplace(resPaths[r], "glsl%i", "glsl100");
|
char *resPathUpdated = TextReplaceAlloc(resPaths[r], "glsl%i", "glsl100");
|
||||||
memset(resPaths[r], 0, 256);
|
memset(resPaths[r], 0, 256);
|
||||||
strcpy(resPaths[r], resPathUpdated);
|
strcpy(resPaths[r], resPathUpdated);
|
||||||
RL_FREE(resPathUpdated);
|
RL_FREE(resPathUpdated);
|
||||||
|
|
@ -2147,7 +2143,7 @@ static int UpdateRequiredFiles(void)
|
||||||
{
|
{
|
||||||
mdIndex += sprintf(mdTextUpdated + mdListStartIndex + mdIndex, TextFormat("\n### category: shaders [%i]\n\n", exCollectionCount));
|
mdIndex += sprintf(mdTextUpdated + mdListStartIndex + mdIndex, TextFormat("\n### category: shaders [%i]\n\n", exCollectionCount));
|
||||||
mdIndex += sprintf(mdTextUpdated + mdListStartIndex + mdIndex,
|
mdIndex += sprintf(mdTextUpdated + mdListStartIndex + mdIndex,
|
||||||
"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.\n\n");
|
"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.h) module.\n\n");
|
||||||
}
|
}
|
||||||
else if (i == 6) // "audio"
|
else if (i == 6) // "audio"
|
||||||
{
|
{
|
||||||
|
|
@ -2498,25 +2494,21 @@ static void SortExampleByName(rlExampleInfo *items, int count)
|
||||||
qsort(items, count, sizeof(rlExampleInfo), rlExampleInfoCompare);
|
qsort(items, count, sizeof(rlExampleInfo), rlExampleInfoCompare);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan resource paths in example file
|
// Scan asset paths from a source code file (raylib)
|
||||||
// WARNING: Supported resource file extensions is hardcoded by used file types
|
// WARNING: Supported asset file extensions are hardcoded by used file types
|
||||||
// but new examples could require other file extensions to be added,
|
// but new examples could require other file extensions to be added
|
||||||
// maybe it should look for '.xxx")' patterns instead
|
static char **LoadExampleResourcePaths(const char *srcFilePath, int *resPathCount)
|
||||||
// TODO: WARNING: Some resources could require linked resources: .fnt --> .png, .mtl --> .png, .gltf --> .png, ...
|
|
||||||
static char **LoadExampleResourcePaths(const char *filePath, int *resPathCount)
|
|
||||||
{
|
{
|
||||||
#define REXM_MAX_RESOURCE_PATH_LEN 256
|
|
||||||
|
|
||||||
char **paths = (char **)RL_CALLOC(REXM_MAX_RESOURCE_PATHS, sizeof(char **));
|
char **paths = (char **)RL_CALLOC(REXM_MAX_RESOURCE_PATHS, sizeof(char **));
|
||||||
for (int i = 0; i < REXM_MAX_RESOURCE_PATHS; i++) paths[i] = (char *)RL_CALLOC(REXM_MAX_RESOURCE_PATH_LEN, sizeof(char));
|
for (int i = 0; i < REXM_MAX_RESOURCE_PATHS; i++) paths[i] = (char *)RL_CALLOC(REXM_MAX_RESOURCE_PATH_LENGTH, sizeof(char));
|
||||||
|
|
||||||
int resCounter = 0;
|
int resCounter = 0;
|
||||||
char *code = LoadFileText(filePath);
|
char *code = LoadFileText(srcFilePath);
|
||||||
|
|
||||||
if (code != NULL)
|
if (code != NULL)
|
||||||
{
|
{
|
||||||
// Resources extensions to check
|
// Resources extensions to check
|
||||||
const char *exts[] = { ".png", ".bmp", ".jpg", ".qoi", ".gif", ".raw", ".hdr", ".ttf", ".fnt", ".wav", ".ogg", ".mp3", ".flac", ".mod", ".qoa", ".obj", ".iqm", ".glb", ".m3d", ".vox", ".vs", ".fs", ".txt" };
|
const char *exts[] = { ".png", ".bmp", ".jpg", ".qoi", ".gif", ".raw", ".hdr", ".ttf", ".fnt", ".wav", ".ogg", ".mp3", ".flac", ".mod", ".xm", ".qoa", ".obj", ".iqm", ".glb", ".m3d", ".vox", ".vs", ".fs", ".txt" };
|
||||||
const int extCount = sizeof(exts)/sizeof(char *);
|
const int extCount = sizeof(exts)/sizeof(char *);
|
||||||
|
|
||||||
char *ptr = code;
|
char *ptr = code;
|
||||||
|
|
@ -2542,9 +2534,9 @@ static char **LoadExampleResourcePaths(const char *filePath, int *resPathCount)
|
||||||
!((functionIndex05 != -1) && (functionIndex05 < 40))) // Not found SaveFileText() before ""
|
!((functionIndex05 != -1) && (functionIndex05 < 40))) // Not found SaveFileText() before ""
|
||||||
{
|
{
|
||||||
int len = (int)(end - start);
|
int len = (int)(end - start);
|
||||||
if ((len > 0) && (len < REXM_MAX_RESOURCE_PATH_LEN))
|
if ((len > 0) && (len < REXM_MAX_RESOURCE_PATH_LENGTH))
|
||||||
{
|
{
|
||||||
char buffer[REXM_MAX_RESOURCE_PATH_LEN] = { 0 };
|
char buffer[REXM_MAX_RESOURCE_PATH_LENGTH] = { 0 };
|
||||||
strncpy(buffer, start, len);
|
strncpy(buffer, start, len);
|
||||||
buffer[len] = '\0';
|
buffer[len] = '\0';
|
||||||
|
|
||||||
|
|
@ -2580,6 +2572,29 @@ static char **LoadExampleResourcePaths(const char *filePath, int *resPathCount)
|
||||||
UnloadFileText(code);
|
UnloadFileText(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// WARNING: Some resources could require linked resources: .fnt --> .png, .mtl --> .png, .gltf --> .png
|
||||||
|
// So doing a recursive pass to scan possible files with second resources
|
||||||
|
int currentAssetCounter = resCounter;
|
||||||
|
for (int i = 0; i < currentAssetCounter; i++)
|
||||||
|
{
|
||||||
|
if (IsFileExtension(paths[i], ".fnt;.gltf"))
|
||||||
|
{
|
||||||
|
int assetCount2 = 0;
|
||||||
|
// ERROR: srcFilePath changes on rcursive call and TextFormat() static arrays are override
|
||||||
|
char **assetPaths2 = LoadExampleResourcePaths(TextFormat("%s/%s", GetDirectoryPath(srcFilePath), paths[i]), &assetCount2);
|
||||||
|
|
||||||
|
for (int j = 0; j < assetCount2; j++)
|
||||||
|
{
|
||||||
|
strcpy(paths[resCounter], TextFormat("%s/%s", GetDirectoryPath(paths[i]) + 2, assetPaths2[j]));
|
||||||
|
resCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnloadExampleResourcePaths(assetPaths2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
*resPathCount = resCounter;
|
*resPathCount = resCounter;
|
||||||
return paths;
|
return paths;
|
||||||
}
|
}
|
||||||
|
|
@ -2815,7 +2830,7 @@ static void UpdateSourceMetadata(const char *exSrcPath, const rlExampleInfo *inf
|
||||||
|
|
||||||
// Update example header title (line #3 - ALWAYS)
|
// Update example header title (line #3 - ALWAYS)
|
||||||
// String: "* raylib [shaders] example - texture drawing"
|
// String: "* raylib [shaders] example - texture drawing"
|
||||||
exTextUpdated[0] = TextReplaceBetween(exTextUpdatedPtr, "* raylib [", "\n",
|
exTextUpdated[0] = TextReplaceBetweenAlloc(exTextUpdatedPtr, "* raylib [", "\n",
|
||||||
TextFormat("%s] example - %s", info->category, exNameFormated));
|
TextFormat("%s] example - %s", info->category, exNameFormated));
|
||||||
if (exTextUpdated[0] != NULL) exTextUpdatedPtr = exTextUpdated[0];
|
if (exTextUpdated[0] != NULL) exTextUpdatedPtr = exTextUpdated[0];
|
||||||
|
|
||||||
|
|
@ -2829,13 +2844,13 @@ static void UpdateSourceMetadata(const char *exSrcPath, const rlExampleInfo *inf
|
||||||
if (i < info->stars) strcpy(starsText + 3*i, "★");
|
if (i < info->stars) strcpy(starsText + 3*i, "★");
|
||||||
else strcpy(starsText + 3*i, "☆");
|
else strcpy(starsText + 3*i, "☆");
|
||||||
}
|
}
|
||||||
exTextUpdated[1] = TextReplaceBetween(exTextUpdatedPtr, "* Example complexity rating: [", "/4\n",
|
exTextUpdated[1] = TextReplaceBetweenAlloc(exTextUpdatedPtr, "* Example complexity rating: [", "/4\n",
|
||||||
TextFormat("%s] %i", starsText, info->stars));
|
TextFormat("%s] %i", starsText, info->stars));
|
||||||
if (exTextUpdated[1] != NULL) exTextUpdatedPtr = exTextUpdated[1];
|
if (exTextUpdated[1] != NULL) exTextUpdatedPtr = exTextUpdated[1];
|
||||||
|
|
||||||
// Update example creation/update raylib versions
|
// Update example creation/update raylib versions
|
||||||
// String: "* Example originally created with raylib 2.0, last time updated with raylib 3.7
|
// String: "* Example originally created with raylib 2.0, last time updated with raylib 3.7
|
||||||
exTextUpdated[2] = TextReplaceBetween(exTextUpdatedPtr, "* Example originally created with raylib ", "\n",
|
exTextUpdated[2] = TextReplaceBetweenAlloc(exTextUpdatedPtr, "* Example originally created with raylib ", "\n",
|
||||||
TextFormat("%s, last time updated with raylib %s", info->verCreated, info->verUpdated));
|
TextFormat("%s, last time updated with raylib %s", info->verCreated, info->verUpdated));
|
||||||
if (exTextUpdated[2] != NULL) exTextUpdatedPtr = exTextUpdated[2];
|
if (exTextUpdated[2] != NULL) exTextUpdatedPtr = exTextUpdated[2];
|
||||||
|
|
||||||
|
|
@ -2843,27 +2858,27 @@ static void UpdateSourceMetadata(const char *exSrcPath, const rlExampleInfo *inf
|
||||||
// String: "* Copyright (c) 2019-2026 Contributor Name (@github_user) and Ramon Santamaria (@raysan5)"
|
// String: "* Copyright (c) 2019-2026 Contributor Name (@github_user) and Ramon Santamaria (@raysan5)"
|
||||||
if (info->yearCreated == info->yearReviewed)
|
if (info->yearCreated == info->yearReviewed)
|
||||||
{
|
{
|
||||||
exTextUpdated[3] = TextReplaceBetween(exTextUpdatedPtr, "Copyright (c) ", ")",
|
exTextUpdated[3] = TextReplaceBetweenAlloc(exTextUpdatedPtr, "Copyright (c) ", ")",
|
||||||
TextFormat("%i %s (@%s", info->yearCreated, info->author, info->authorGitHub));
|
TextFormat("%i %s (@%s", info->yearCreated, info->author, info->authorGitHub));
|
||||||
if (exTextUpdated[3] != NULL) exTextUpdatedPtr = exTextUpdated[3];
|
if (exTextUpdated[3] != NULL) exTextUpdatedPtr = exTextUpdated[3];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
exTextUpdated[3] = TextReplaceBetween(exTextUpdatedPtr, "Copyright (c) ", ")",
|
exTextUpdated[3] = TextReplaceBetweenAlloc(exTextUpdatedPtr, "Copyright (c) ", ")",
|
||||||
TextFormat("%i-%i %s (@%s", info->yearCreated, info->yearReviewed, info->author, info->authorGitHub));
|
TextFormat("%i-%i %s (@%s", info->yearCreated, info->yearReviewed, info->author, info->authorGitHub));
|
||||||
if (exTextUpdated[3] != NULL) exTextUpdatedPtr = exTextUpdated[3];
|
if (exTextUpdated[3] != NULL) exTextUpdatedPtr = exTextUpdated[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update window title
|
// Update window title
|
||||||
// String: "InitWindow(screenWidth, screenHeight, "raylib [shaders] example - texture drawing");"
|
// String: "InitWindow(screenWidth, screenHeight, "raylib [shaders] example - texture drawing");"
|
||||||
exTextUpdated[4] = TextReplaceBetween(exTextUpdated[3], "InitWindow(screenWidth, screenHeight, \"", "\");",
|
exTextUpdated[4] = TextReplaceBetweenAlloc(exTextUpdated[3], "InitWindow(screenWidth, screenHeight, \"", "\");",
|
||||||
TextFormat("raylib [%s] example - %s", info->category, exNameFormated));
|
TextFormat("raylib [%s] example - %s", info->category, exNameFormated));
|
||||||
if (exTextUpdated[4] != NULL) exTextUpdatedPtr = exTextUpdated[4];
|
if (exTextUpdated[4] != NULL) exTextUpdatedPtr = exTextUpdated[4];
|
||||||
|
|
||||||
// Update contributors names
|
// Update contributors names
|
||||||
// String: "* Example contributed by Contributor Name (@github_user) and reviewed by Ramon Santamaria (@raysan5)"
|
// String: "* Example contributed by Contributor Name (@github_user) and reviewed by Ramon Santamaria (@raysan5)"
|
||||||
// WARNING: Not all examples are contributed by someone, so the result of this replace can be NULL (string not found)
|
// WARNING: Not all examples are contributed by someone, so the result of this replace can be NULL (string not found)
|
||||||
exTextUpdated[5] = TextReplaceBetween(exTextUpdatedPtr, "* Example contributed by ", ")",
|
exTextUpdated[5] = TextReplaceBetweenAlloc(exTextUpdatedPtr, "* Example contributed by ", ")",
|
||||||
TextFormat("%s (@%s", info->author, info->authorGitHub));
|
TextFormat("%s (@%s", info->author, info->authorGitHub));
|
||||||
if (exTextUpdated[5] != NULL) exTextUpdatedPtr = exTextUpdated[5];
|
if (exTextUpdated[5] != NULL) exTextUpdatedPtr = exTextUpdated[5];
|
||||||
|
|
||||||
|
|
@ -2910,14 +2925,14 @@ static void UpdateWebMetadata(const char *exHtmlPath, const char *exFilePath)
|
||||||
UnloadFileText(exText);
|
UnloadFileText(exText);
|
||||||
|
|
||||||
// Update example.html required text
|
// Update example.html required text
|
||||||
exHtmlTextUpdated[0] = TextReplace(exHtmlText, "raylib web game", exTitle);
|
exHtmlTextUpdated[0] = TextReplaceAlloc(exHtmlText, "raylib web game", exTitle);
|
||||||
exHtmlTextUpdated[1] = TextReplace(exHtmlTextUpdated[0], "New raylib web videogame, developed using raylib videogames library", exDescription);
|
exHtmlTextUpdated[1] = TextReplaceAlloc(exHtmlTextUpdated[0], "New raylib web videogame, developed using raylib videogames library", exDescription);
|
||||||
exHtmlTextUpdated[2] = TextReplace(exHtmlTextUpdated[1], "https://www.raylib.com/common/raylib_logo.png",
|
exHtmlTextUpdated[2] = TextReplaceAlloc(exHtmlTextUpdated[1], "https://www.raylib.com/common/raylib_logo.png",
|
||||||
TextFormat("https://raw.githubusercontent.com/raysan5/raylib/master/examples/%s/%s.png", exCategory, exName));
|
TextFormat("https://raw.githubusercontent.com/raysan5/raylib/master/examples/%s/%s.png", exCategory, exName));
|
||||||
exHtmlTextUpdated[3] = TextReplace(exHtmlTextUpdated[2], "https://www.raylib.com/games.html",
|
exHtmlTextUpdated[3] = TextReplaceAlloc(exHtmlTextUpdated[2], "https://www.raylib.com/games.html",
|
||||||
TextFormat("https://www.raylib.com/examples/%s/%s.html", exCategory, exName));
|
TextFormat("https://www.raylib.com/examples/%s/%s.html", exCategory, exName));
|
||||||
exHtmlTextUpdated[4] = TextReplace(exHtmlTextUpdated[3], "raylib - example", TextFormat("raylib - %s", exName)); // og:site_name
|
exHtmlTextUpdated[4] = TextReplaceAlloc(exHtmlTextUpdated[3], "raylib - example", TextFormat("raylib - %s", exName)); // og:site_name
|
||||||
exHtmlTextUpdated[5] = TextReplace(exHtmlTextUpdated[4], "https://github.com/raysan5/raylib",
|
exHtmlTextUpdated[5] = TextReplaceAlloc(exHtmlTextUpdated[4], "https://github.com/raysan5/raylib",
|
||||||
TextFormat("https://github.com/raysan5/raylib/blob/master/examples/%s/%s.c", exCategory, exName));
|
TextFormat("https://github.com/raysan5/raylib/blob/master/examples/%s/%s.c", exCategory, exName));
|
||||||
|
|
||||||
SaveFileText(exHtmlPathCopy, exHtmlTextUpdated[5]);
|
SaveFileText(exHtmlPathCopy, exHtmlTextUpdated[5]);
|
||||||
|
|
|
||||||
|
|
@ -4685,7 +4685,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "LoadDirectoryFiles",
|
"name": "LoadDirectoryFiles",
|
||||||
"description": "Load directory filepaths",
|
"description": "Load directory filepaths, files and directories, no subdirs scan",
|
||||||
"returnType": "FilePathList",
|
"returnType": "FilePathList",
|
||||||
"params": [
|
"params": [
|
||||||
{
|
{
|
||||||
|
|
@ -4696,7 +4696,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "LoadDirectoryFilesEx",
|
"name": "LoadDirectoryFilesEx",
|
||||||
"description": "Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result",
|
"description": "Load directory filepaths with extension filtering and subdir scan; some filters available: "*.*", "FILES*", "DIRS*"",
|
||||||
"returnType": "FilePathList",
|
"returnType": "FilePathList",
|
||||||
"params": [
|
"params": [
|
||||||
{
|
{
|
||||||
|
|
@ -7231,7 +7231,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ExportImageToMemory",
|
"name": "ExportImageToMemory",
|
||||||
"description": "Export image to memory buffer",
|
"description": "Export image to memory buffer, memory must be MemFree()",
|
||||||
"returnType": "unsigned char *",
|
"returnType": "unsigned char *",
|
||||||
"params": [
|
"params": [
|
||||||
{
|
{
|
||||||
|
|
@ -9946,7 +9946,26 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "TextReplace",
|
"name": "TextReplace",
|
||||||
"description": "Replace text string (WARNING: memory must be freed!)",
|
"description": "Replace text string with new string",
|
||||||
|
"returnType": "char *",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"type": "const char *",
|
||||||
|
"name": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "const char *",
|
||||||
|
"name": "search"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "const char *",
|
||||||
|
"name": "replacement"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "TextReplaceAlloc",
|
||||||
|
"description": "Replace text string with new string, memory must be MemFree()",
|
||||||
"returnType": "char *",
|
"returnType": "char *",
|
||||||
"params": [
|
"params": [
|
||||||
{
|
{
|
||||||
|
|
@ -9965,7 +9984,30 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "TextReplaceBetween",
|
"name": "TextReplaceBetween",
|
||||||
"description": "Replace text between two specific strings (WARNING: memory must be freed!)",
|
"description": "Replace text between two specific strings",
|
||||||
|
"returnType": "char *",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"type": "const char *",
|
||||||
|
"name": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "const char *",
|
||||||
|
"name": "begin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "const char *",
|
||||||
|
"name": "end"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "const char *",
|
||||||
|
"name": "replacement"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "TextReplaceBetweenAlloc",
|
||||||
|
"description": "Replace text between two specific strings, memory must be MemFree()",
|
||||||
"returnType": "char *",
|
"returnType": "char *",
|
||||||
"params": [
|
"params": [
|
||||||
{
|
{
|
||||||
|
|
@ -9988,7 +10030,26 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "TextInsert",
|
"name": "TextInsert",
|
||||||
"description": "Insert text in a position (WARNING: memory must be freed!)",
|
"description": "Insert text in a defined byte position",
|
||||||
|
"returnType": "char *",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"type": "const char *",
|
||||||
|
"name": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "const char *",
|
||||||
|
"name": "insert"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "int",
|
||||||
|
"name": "position"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "TextInsertAlloc",
|
||||||
|
"description": "Insert text in a defined byte position, memory must be MemFree()",
|
||||||
"returnType": "char *",
|
"returnType": "char *",
|
||||||
"params": [
|
"params": [
|
||||||
{
|
{
|
||||||
|
|
@ -10820,60 +10881,6 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "DrawModelPoints",
|
|
||||||
"description": "Draw a model as points",
|
|
||||||
"returnType": "void",
|
|
||||||
"params": [
|
|
||||||
{
|
|
||||||
"type": "Model",
|
|
||||||
"name": "model"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "Vector3",
|
|
||||||
"name": "position"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "float",
|
|
||||||
"name": "scale"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "Color",
|
|
||||||
"name": "tint"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "DrawModelPointsEx",
|
|
||||||
"description": "Draw a model as points with extended parameters",
|
|
||||||
"returnType": "void",
|
|
||||||
"params": [
|
|
||||||
{
|
|
||||||
"type": "Model",
|
|
||||||
"name": "model"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "Vector3",
|
|
||||||
"name": "position"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "Vector3",
|
|
||||||
"name": "rotationAxis"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "float",
|
|
||||||
"name": "rotationAngle"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "Vector3",
|
|
||||||
"name": "scale"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "Color",
|
|
||||||
"name": "tint"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "DrawBoundingBox",
|
"name": "DrawBoundingBox",
|
||||||
"description": "Draw bounding box (wires)",
|
"description": "Draw bounding box (wires)",
|
||||||
|
|
|
||||||
|
|
@ -4199,7 +4199,7 @@ return {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "LoadDirectoryFiles",
|
name = "LoadDirectoryFiles",
|
||||||
description = "Load directory filepaths",
|
description = "Load directory filepaths, files and directories, no subdirs scan",
|
||||||
returnType = "FilePathList",
|
returnType = "FilePathList",
|
||||||
params = {
|
params = {
|
||||||
{type = "const char *", name = "dirPath"}
|
{type = "const char *", name = "dirPath"}
|
||||||
|
|
@ -4207,7 +4207,7 @@ return {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "LoadDirectoryFilesEx",
|
name = "LoadDirectoryFilesEx",
|
||||||
description = "Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result",
|
description = "Load directory filepaths with extension filtering and subdir scan; some filters available: "*.*", "FILES*", "DIRS*"",
|
||||||
returnType = "FilePathList",
|
returnType = "FilePathList",
|
||||||
params = {
|
params = {
|
||||||
{type = "const char *", name = "basePath"},
|
{type = "const char *", name = "basePath"},
|
||||||
|
|
@ -5596,7 +5596,7 @@ return {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "ExportImageToMemory",
|
name = "ExportImageToMemory",
|
||||||
description = "Export image to memory buffer",
|
description = "Export image to memory buffer, memory must be MemFree()",
|
||||||
returnType = "unsigned char *",
|
returnType = "unsigned char *",
|
||||||
params = {
|
params = {
|
||||||
{type = "Image", name = "image"},
|
{type = "Image", name = "image"},
|
||||||
|
|
@ -7045,7 +7045,17 @@ return {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "TextReplace",
|
name = "TextReplace",
|
||||||
description = "Replace text string (WARNING: memory must be freed!)",
|
description = "Replace text string with new string",
|
||||||
|
returnType = "char *",
|
||||||
|
params = {
|
||||||
|
{type = "const char *", name = "text"},
|
||||||
|
{type = "const char *", name = "search"},
|
||||||
|
{type = "const char *", name = "replacement"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name = "TextReplaceAlloc",
|
||||||
|
description = "Replace text string with new string, memory must be MemFree()",
|
||||||
returnType = "char *",
|
returnType = "char *",
|
||||||
params = {
|
params = {
|
||||||
{type = "const char *", name = "text"},
|
{type = "const char *", name = "text"},
|
||||||
|
|
@ -7055,7 +7065,18 @@ return {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "TextReplaceBetween",
|
name = "TextReplaceBetween",
|
||||||
description = "Replace text between two specific strings (WARNING: memory must be freed!)",
|
description = "Replace text between two specific strings",
|
||||||
|
returnType = "char *",
|
||||||
|
params = {
|
||||||
|
{type = "const char *", name = "text"},
|
||||||
|
{type = "const char *", name = "begin"},
|
||||||
|
{type = "const char *", name = "end"},
|
||||||
|
{type = "const char *", name = "replacement"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name = "TextReplaceBetweenAlloc",
|
||||||
|
description = "Replace text between two specific strings, memory must be MemFree()",
|
||||||
returnType = "char *",
|
returnType = "char *",
|
||||||
params = {
|
params = {
|
||||||
{type = "const char *", name = "text"},
|
{type = "const char *", name = "text"},
|
||||||
|
|
@ -7066,7 +7087,17 @@ return {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "TextInsert",
|
name = "TextInsert",
|
||||||
description = "Insert text in a position (WARNING: memory must be freed!)",
|
description = "Insert text in a defined byte position",
|
||||||
|
returnType = "char *",
|
||||||
|
params = {
|
||||||
|
{type = "const char *", name = "text"},
|
||||||
|
{type = "const char *", name = "insert"},
|
||||||
|
{type = "int", name = "position"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name = "TextInsertAlloc",
|
||||||
|
description = "Insert text in a defined byte position, memory must be MemFree()",
|
||||||
returnType = "char *",
|
returnType = "char *",
|
||||||
params = {
|
params = {
|
||||||
{type = "const char *", name = "text"},
|
{type = "const char *", name = "text"},
|
||||||
|
|
@ -7493,30 +7524,6 @@ return {
|
||||||
{type = "Color", name = "tint"}
|
{type = "Color", name = "tint"}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name = "DrawModelPoints",
|
|
||||||
description = "Draw a model as points",
|
|
||||||
returnType = "void",
|
|
||||||
params = {
|
|
||||||
{type = "Model", name = "model"},
|
|
||||||
{type = "Vector3", name = "position"},
|
|
||||||
{type = "float", name = "scale"},
|
|
||||||
{type = "Color", name = "tint"}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name = "DrawModelPointsEx",
|
|
||||||
description = "Draw a model as points with extended parameters",
|
|
||||||
returnType = "void",
|
|
||||||
params = {
|
|
||||||
{type = "Model", name = "model"},
|
|
||||||
{type = "Vector3", name = "position"},
|
|
||||||
{type = "Vector3", name = "rotationAxis"},
|
|
||||||
{type = "float", name = "rotationAngle"},
|
|
||||||
{type = "Vector3", name = "scale"},
|
|
||||||
{type = "Color", name = "tint"}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name = "DrawBoundingBox",
|
name = "DrawBoundingBox",
|
||||||
description = "Draw bounding box (wires)",
|
description = "Draw bounding box (wires)",
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -682,7 +682,7 @@
|
||||||
<Param type="unsigned int" name="frames" desc="" />
|
<Param type="unsigned int" name="frames" desc="" />
|
||||||
</Callback>
|
</Callback>
|
||||||
</Callbacks>
|
</Callbacks>
|
||||||
<Functions count="599">
|
<Functions count="600">
|
||||||
<Function name="InitWindow" retType="void" paramCount="3" desc="Initialize window and OpenGL context">
|
<Function name="InitWindow" retType="void" paramCount="3" desc="Initialize window and OpenGL context">
|
||||||
<Param type="int" name="width" desc="" />
|
<Param type="int" name="width" desc="" />
|
||||||
<Param type="int" name="height" desc="" />
|
<Param type="int" name="height" desc="" />
|
||||||
|
|
@ -1122,10 +1122,10 @@
|
||||||
<Function name="IsFileNameValid" retType="bool" paramCount="1" desc="Check if fileName is valid for the platform/OS">
|
<Function name="IsFileNameValid" retType="bool" paramCount="1" desc="Check if fileName is valid for the platform/OS">
|
||||||
<Param type="const char *" name="fileName" desc="" />
|
<Param type="const char *" name="fileName" desc="" />
|
||||||
</Function>
|
</Function>
|
||||||
<Function name="LoadDirectoryFiles" retType="FilePathList" paramCount="1" desc="Load directory filepaths">
|
<Function name="LoadDirectoryFiles" retType="FilePathList" paramCount="1" desc="Load directory filepaths, files and directories, no subdirs scan">
|
||||||
<Param type="const char *" name="dirPath" desc="" />
|
<Param type="const char *" name="dirPath" desc="" />
|
||||||
</Function>
|
</Function>
|
||||||
<Function name="LoadDirectoryFilesEx" retType="FilePathList" paramCount="3" desc="Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result">
|
<Function name="LoadDirectoryFilesEx" retType="FilePathList" paramCount="3" desc="Load directory filepaths with extension filtering and subdir scan; some filters available: "*.*", "FILES*", "DIRS*"">
|
||||||
<Param type="const char *" name="basePath" desc="" />
|
<Param type="const char *" name="basePath" desc="" />
|
||||||
<Param type="const char *" name="filter" desc="" />
|
<Param type="const char *" name="filter" desc="" />
|
||||||
<Param type="bool" name="scanSubdirs" desc="" />
|
<Param type="bool" name="scanSubdirs" desc="" />
|
||||||
|
|
@ -1809,7 +1809,7 @@
|
||||||
<Param type="Image" name="image" desc="" />
|
<Param type="Image" name="image" desc="" />
|
||||||
<Param type="const char *" name="fileName" desc="" />
|
<Param type="const char *" name="fileName" desc="" />
|
||||||
</Function>
|
</Function>
|
||||||
<Function name="ExportImageToMemory" retType="unsigned char *" paramCount="3" desc="Export image to memory buffer">
|
<Function name="ExportImageToMemory" retType="unsigned char *" paramCount="3" desc="Export image to memory buffer, memory must be MemFree()">
|
||||||
<Param type="Image" name="image" desc="" />
|
<Param type="Image" name="image" desc="" />
|
||||||
<Param type="const char *" name="fileType" desc="" />
|
<Param type="const char *" name="fileType" desc="" />
|
||||||
<Param type="int *" name="fileSize" desc="" />
|
<Param type="int *" name="fileSize" desc="" />
|
||||||
|
|
@ -2525,18 +2525,34 @@
|
||||||
<Param type="const char *" name="begin" desc="" />
|
<Param type="const char *" name="begin" desc="" />
|
||||||
<Param type="const char *" name="end" desc="" />
|
<Param type="const char *" name="end" desc="" />
|
||||||
</Function>
|
</Function>
|
||||||
<Function name="TextReplace" retType="char *" paramCount="3" desc="Replace text string (WARNING: memory must be freed!)">
|
<Function name="TextReplace" retType="char *" paramCount="3" desc="Replace text string with new string">
|
||||||
<Param type="const char *" name="text" desc="" />
|
<Param type="const char *" name="text" desc="" />
|
||||||
<Param type="const char *" name="search" desc="" />
|
<Param type="const char *" name="search" desc="" />
|
||||||
<Param type="const char *" name="replacement" desc="" />
|
<Param type="const char *" name="replacement" desc="" />
|
||||||
</Function>
|
</Function>
|
||||||
<Function name="TextReplaceBetween" retType="char *" paramCount="4" desc="Replace text between two specific strings (WARNING: memory must be freed!)">
|
<Function name="TextReplaceAlloc" retType="char *" paramCount="3" desc="Replace text string with new string, memory must be MemFree()">
|
||||||
|
<Param type="const char *" name="text" desc="" />
|
||||||
|
<Param type="const char *" name="search" desc="" />
|
||||||
|
<Param type="const char *" name="replacement" desc="" />
|
||||||
|
</Function>
|
||||||
|
<Function name="TextReplaceBetween" retType="char *" paramCount="4" desc="Replace text between two specific strings">
|
||||||
<Param type="const char *" name="text" desc="" />
|
<Param type="const char *" name="text" desc="" />
|
||||||
<Param type="const char *" name="begin" desc="" />
|
<Param type="const char *" name="begin" desc="" />
|
||||||
<Param type="const char *" name="end" desc="" />
|
<Param type="const char *" name="end" desc="" />
|
||||||
<Param type="const char *" name="replacement" desc="" />
|
<Param type="const char *" name="replacement" desc="" />
|
||||||
</Function>
|
</Function>
|
||||||
<Function name="TextInsert" retType="char *" paramCount="3" desc="Insert text in a position (WARNING: memory must be freed!)">
|
<Function name="TextReplaceBetweenAlloc" retType="char *" paramCount="4" desc="Replace text between two specific strings, memory must be MemFree()">
|
||||||
|
<Param type="const char *" name="text" desc="" />
|
||||||
|
<Param type="const char *" name="begin" desc="" />
|
||||||
|
<Param type="const char *" name="end" desc="" />
|
||||||
|
<Param type="const char *" name="replacement" desc="" />
|
||||||
|
</Function>
|
||||||
|
<Function name="TextInsert" retType="char *" paramCount="3" desc="Insert text in a defined byte position">
|
||||||
|
<Param type="const char *" name="text" desc="" />
|
||||||
|
<Param type="const char *" name="insert" desc="" />
|
||||||
|
<Param type="int" name="position" desc="" />
|
||||||
|
</Function>
|
||||||
|
<Function name="TextInsertAlloc" retType="char *" paramCount="3" desc="Insert text in a defined byte position, memory must be MemFree()">
|
||||||
<Param type="const char *" name="text" desc="" />
|
<Param type="const char *" name="text" desc="" />
|
||||||
<Param type="const char *" name="insert" desc="" />
|
<Param type="const char *" name="insert" desc="" />
|
||||||
<Param type="int" name="position" desc="" />
|
<Param type="int" name="position" desc="" />
|
||||||
|
|
@ -2755,20 +2771,6 @@
|
||||||
<Param type="Vector3" name="scale" desc="" />
|
<Param type="Vector3" name="scale" desc="" />
|
||||||
<Param type="Color" name="tint" desc="" />
|
<Param type="Color" name="tint" desc="" />
|
||||||
</Function>
|
</Function>
|
||||||
<Function name="DrawModelPoints" retType="void" paramCount="4" desc="Draw a model as points">
|
|
||||||
<Param type="Model" name="model" desc="" />
|
|
||||||
<Param type="Vector3" name="position" desc="" />
|
|
||||||
<Param type="float" name="scale" desc="" />
|
|
||||||
<Param type="Color" name="tint" desc="" />
|
|
||||||
</Function>
|
|
||||||
<Function name="DrawModelPointsEx" retType="void" paramCount="6" desc="Draw a model as points with extended parameters">
|
|
||||||
<Param type="Model" name="model" desc="" />
|
|
||||||
<Param type="Vector3" name="position" desc="" />
|
|
||||||
<Param type="Vector3" name="rotationAxis" desc="" />
|
|
||||||
<Param type="float" name="rotationAngle" desc="" />
|
|
||||||
<Param type="Vector3" name="scale" desc="" />
|
|
||||||
<Param type="Color" name="tint" desc="" />
|
|
||||||
</Function>
|
|
||||||
<Function name="DrawBoundingBox" retType="void" paramCount="2" desc="Draw bounding box (wires)">
|
<Function name="DrawBoundingBox" retType="void" paramCount="2" desc="Draw bounding box (wires)">
|
||||||
<Param type="BoundingBox" name="box" desc="" />
|
<Param type="BoundingBox" name="box" desc="" />
|
||||||
<Param type="Color" name="color" desc="" />
|
<Param type="Color" name="color" desc="" />
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,10 @@
|
||||||
- struct AliasInfo
|
- struct AliasInfo
|
||||||
- struct EnumInfo
|
- struct EnumInfo
|
||||||
- struct FunctionInfo
|
- struct FunctionInfo
|
||||||
|
|
||||||
WARNING: This parser is specifically designed to work with raylib.h, and has some contraints
|
WARNING: This parser is specifically designed to work with raylib.h, and has some contraints
|
||||||
in that regards. Still, it can also work with other header files that follow same file structure
|
in that regards. Still, it can also work with other header files that follow same file structure
|
||||||
conventions as raylib.h: rlgl.h, raymath.h, raygui.h, reasings.h
|
conventions as raylib.h: rlgl.h, raymath.h, raygui.h, reasings.h
|
||||||
|
|
||||||
CONSTRAINTS:
|
CONSTRAINTS:
|
||||||
This parser is specifically designed to work with raylib.h, so, it has some constraints:
|
This parser is specifically designed to work with raylib.h, so, it has some constraints:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user