diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 79b0d8a..b4084a5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,25 +8,50 @@ on: jobs: build_autotools: - name: Autotools / ${{ matrix.os }} + name: Autotools / ${{ matrix.os }} / ${{ matrix.simd }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: [macos-12, macos-14, ubuntu-22.04] + os: [macos-13, macos-14, ubuntu-22.04, ubuntu-24.04] + simd: [none, sse, sse2, sse3, sse4, avx, avx2, neon] steps: - uses: actions/checkout@v4 - - name: Install Autotools + - name: Install Autotools on macOS if: runner.os == 'macOS' run: brew upgrade && brew install autoconf automake libtool + - name: Install Autotools on Ubuntu + if: matrix.os == 'ubuntu-22.04' || matrix.os == 'ubuntu-24.04' + run: sudo apt-get install -y autoconf automake libtool + + - name: Set SIMD flags + run: | + if [ "${{ matrix.simd }}" == "none" ]; then + export CFLAGS="" + elif [ "${{ matrix.simd }}" == "sse" ]; then + export CFLAGS="-msse" + elif [ "${{ matrix.simd }}" == "sse2" ]; then + export CFLAGS="-msse2" + elif [ "${{ matrix.simd }}" == "sse3" ]; then + export CFLAGS="-msse3" + elif [ "${{ matrix.simd }}" == "sse4" ]; then + export CFLAGS="-msse4" + elif [ "${{ matrix.simd }}" == "avx" ]; then + export CFLAGS="-mavx" + elif [ "${{ matrix.simd }}" == "avx2" ]; then + export CFLAGS="-mavx2" + elif [ "${{ matrix.simd }}" == "neon" ]; then + export CFLAGS="-mfpu=neon" + fi + - name: Generate Autotools run: ./autogen.sh - name: Configure Autotools - run: ./configure + run: ./configure CFLAGS="$CFLAGS" - name: Build run: make @@ -55,13 +80,72 @@ jobs: - name: Build run: cmake --build build + build_cmake_ubuntu: + name: CMake / ${{ matrix.target.os }} / ${{ matrix.target.cc }} / ${{ matrix.simd }} + runs-on: ${{ matrix.target.os }} + strategy: + fail-fast: false + matrix: + target: + - { os: ubuntu-20.04, cc: gcc-11 } + - { os: ubuntu-22.04, cc: gcc-12 } + - { os: ubuntu-24.04, cc: gcc-13 } + - { os: ubuntu-20.04, cc: clang-12 } + - { os: ubuntu-22.04, cc: clang-15 } + simd: [none, sse, sse2, sse3, sse4, avx, avx2, neon] + + steps: + - uses: actions/checkout@v4 + + - name: Add Ubuntu Toolchain PPA + if: matrix.target.os == 'ubuntu-20.04' + run: | + sudo apt-get update + sudo apt-get install -y software-properties-common + sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test + sudo apt-get update + + - name: Install Compiler and Ninja + run: | + sudo apt-get install -y ${{ matrix.target.cc }} ninja-build + + - name: Set SIMD flags + run: | + if [ "${{ matrix.simd }}" == "none" ]; then + export CFLAGS="" + elif [ "${{ matrix.simd }}" == "sse" ]; then + export CFLAGS="-msse" + elif [ "${{ matrix.simd }}" == "sse2" ]; then + export CFLAGS="-msse2" + elif [ "${{ matrix.simd }}" == "sse3" ]; then + export CFLAGS="-msse3" + elif [ "${{ matrix.simd }}" == "sse4" ]; then + export CFLAGS="-msse4" + elif [ "${{ matrix.simd }}" == "avx" ]; then + export CFLAGS="-mavx" + elif [ "${{ matrix.simd }}" == "avx2" ]; then + export CFLAGS="-mavx2" + elif [ "${{ matrix.simd }}" == "neon" ]; then + export CFLAGS="-mfpu=neon" + fi + + - name: Configure CMake + run: cmake -B build -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=${{ matrix.target.cc }} -DCMAKE_C_FLAGS="$CFLAGS" -DCGLM_STATIC=ON -DCGLM_USE_TEST=ON + + - name: Build + run: cmake --build build + + - name: Test + working-directory: build + run: ./tests + build_cmake_macos: name: CMake / ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: [macos-12, macos-14] + os: [macos-13, macos-14] steps: - uses: actions/checkout@v4 @@ -86,76 +170,217 @@ jobs: working-directory: build run: ./tests - build_cmake_ubuntu: - name: CMake / ${{ matrix.target.os }} / ${{ matrix.target.cc }} - runs-on: ${{ matrix.target.os }} + build_cmake: + name: CMake / ${{ matrix.os }} / ${{ matrix.simd }} + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - target: - - { os: ubuntu-20.04, cc: gcc-11 } - - { os: ubuntu-22.04, cc: gcc-12 } - - { os: ubuntu-22.04, cc: gcc-13 } - - { os: ubuntu-20.04, cc: clang-12 } - - { os: ubuntu-22.04, cc: clang-15 } + os: [macos-13, macos-14, windows-2022] + simd: [none, sse, sse2, sse3, sse4, avx, avx2, neon] + steps: - uses: actions/checkout@v4 - - name: Install Compiler and Ninja - run: | - sudo apt-get update -y - sudo apt-get install -y ${{ matrix.target.cc }} ninja-build + - name: Install Ninja on macOS + if: runner.os == 'macOS' + run: brew upgrade && brew install ninja - - name: Configure CMake + - name: Set SIMD flags (Windows) + if: runner.os == 'Windows' + shell: pwsh run: | - cmake \ - -B build \ - -GNinja \ - -DCMAKE_C_COMPILER=${{ matrix.target.cc }} \ - -DCMAKE_BUILD_TYPE=Release \ - -DCGLM_STATIC=ON \ - -DCGLM_USE_TEST=ON + $simd = "${{ matrix.simd }}" + if ($simd -eq "none") { + $env:CFLAGS = "" + } elseif ($simd -eq "sse") { + $env:CFLAGS = "-arch:SSE" + } elseif ($simd -eq "sse2") { + $env:CFLAGS = "-arch:SSE2" + } elseif ($simd -eq "sse3") { + $env:CFLAGS = "-arch:SSE3" + } elseif ($simd -eq "sse4") { + $env:CFLAGS = "-arch:SSE4" + } elseif ($simd -eq "avx") { + $env:CFLAGS = "-arch:AVX" + } elseif ($simd -eq "avx2") { + $env:CFLAGS = "-arch:AVX2" + } elseif ($simd -eq "neon") { + $env:CFLAGS = "-arch:NEON" + } + + - name: Set SIMD flags (Unix) + if: runner.os != 'Windows' + shell: bash + run: | + if [ "${{ matrix.simd }}" == "none" ]; then + export CFLAGS="" + elif [ "${{ matrix.simd }}" == "sse" ]; then + export CFLAGS="-msse" + elif [ "${{ matrix.simd }}" == "sse2" ]; then + export CFLAGS="-msse2" + elif [ "${{ matrix.simd }}" == "sse3" ]; then + export CFLAGS="-msse3" + elif [ "${{ matrix.simd }}" == "sse4" ]; then + export CFLAGS="-msse4" + elif [ "${{ matrix.simd }}" == "avx" ]; then + export CFLAGS="-mavx" + elif [ "${{ matrix.simd }}" == "avx2" ]; then + export CFLAGS="-mavx2" + elif [ "${{ matrix.simd }}" == "neon" ]; then + export CFLAGS="-mfpu=neon" + fi + + - name: Configure CMake (Windows) + if: runner.os == 'Windows' + shell: pwsh + run: cmake -B build -G "Visual Studio 17 2022" -A x64 -T host=x64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS="$env:CFLAGS" -DCGLM_STATIC=ON -DCGLM_USE_TEST=ON + + - name: Configure CMake (Unix) + if: runner.os != 'Windows' + shell: bash + run: cmake -B build -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS="$CFLAGS" -DCGLM_STATIC=ON -DCGLM_USE_TEST=ON - name: Build run: cmake --build build - - name: Test + - name: Test (Windows) + if: runner.os == 'Windows' + shell: pwsh + working-directory: build + run: .\Debug\tests.exe + + - name: Test (Unix) + if: runner.os != 'Windows' + shell: bash working-directory: build run: ./tests - build_cmake_windows: - name: CMake / ${{ matrix.platform.name }} - runs-on: windows-2022 + build_meson: + name: Meson / ${{ matrix.os }} / ${{ matrix.simd }} + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - platform: - - { name: Windows (x64), flags: -A x64 } - - { name: Windows (x86), flags: -A Win32 } - - { name: Windows (clang-cl x64), flags: -T ClangCL -A x64 } - - { name: Windows (clang-cl x86), flags: -T ClangCL -A Win32 } - - { name: Windows (ARM), flags: -A ARM, skip_tests: true, skip_build: true } # This fails to build. - - { name: Windows (ARM64), flags: -A ARM64, skip_tests: true } - - { name: UWP (ARM64), flags: -A ARM64, -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION="10.0", skip_tests: true } - - { name: UWP (x64), flags: -A x64 -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION="10.0", skip_tests: true } + os: [macos-14, ubuntu-22.04, ubuntu-24.04, windows-2022] + simd: [none, sse, sse2, sse3, sse4, avx, avx2, neon] steps: - uses: actions/checkout@v4 - - name: Configure CMake - run: cmake -B build ` - -DCGLM_STATIC=ON ` - -DCGLM_USE_TEST=ON ` - ${{ matrix.platform.flags }} + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + cache: 'pip' - - name: Build - if: ${{ !matrix.platform.skip_build }} - run: cmake --build build --config Release --parallel + - name: Install meson + run: python3 -m pip install meson ninja - - name: Test - if: ${{ !matrix.platform.skip_tests }} - working-directory: build - run: .\Release\tests.exe + - name: Set SIMD flags (Windows) + if: runner.os == 'Windows' + shell: pwsh + run: | + $simd = "${{ matrix.simd }}" + if ($simd -eq "none") { + $env:CFLAGS = "" + } elseif ($simd -eq "sse") { + $env:CFLAGS = "-arch:SSE" + } elseif ($simd -eq "sse2") { + $env:CFLAGS = "-arch:SSE2" + } elseif ($simd -eq "sse3") { + $env:CFLAGS = "-arch:SSE3" + } elseif ($simd -eq "sse4") { + $env:CFLAGS = "-arch:SSE4" + } elseif ($simd -eq "avx") { + $env:CFLAGS = "-arch:AVX" + } elseif ($simd -eq "avx2") { + $env:CFLAGS = "-arch:AVX2" + } elseif ($simd -eq "neon") { + $env:CFLAGS = "-arch:NEON" + } + + - name: Set SIMD flags (Unix) + if: runner.os != 'Windows' + shell: bash + run: | + if [ "${{ matrix.simd }}" == "none" ]; then + export CFLAGS="" + elif [ "${{ matrix.simd }}" == "sse" ]; then + export CFLAGS="-msse" + elif [ "${{ matrix.simd }}" == "sse2" ]; then + export CFLAGS="-msse2" + elif [ "${{ matrix.simd }}" == "sse3" ]; then + export CFLAGS="-msse3" + elif [ "${{ matrix.simd }}" == "sse4" ]; then + export CFLAGS="-msse4" + elif [ "${{ matrix.simd }}" == "avx" ]; then + export CFLAGS="-mavx" + elif [ "${{ matrix.simd }}" == "avx2" ]; then + export CFLAGS="-mavx2" + elif [ "${{ matrix.simd }}" == "neon" ]; then + export CFLAGS="-mfpu=neon" + fi + + - name: Build with meson (Windows) + if: runner.os == 'Windows' + shell: pwsh + run: | + meson setup build -Dbuildtype=release --default-library=static -Dbuild_tests=true -Dc_args="$env:CFLAGS" + meson test -C build + + - name: Build with meson (Unix) + if: runner.os != 'Windows' + shell: bash + run: | + meson setup build -Dbuildtype=release --default-library=static -Dbuild_tests=true -Dc_args="$CFLAGS" + meson test -C build + + build_msbuild: + name: MSBuild / Windows / ${{ matrix.simd }} + runs-on: windows-2022 + strategy: + fail-fast: false + matrix: + simd: [none, sse, sse2, sse3, sse4, avx, avx2, neon] + + steps: + - uses: actions/checkout@v4 + + - uses: microsoft/setup-msbuild@v2 + + - name: Retarget solution + run: | + vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath + $vsInstallPath = vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath + & "$vsInstallPath\Common7\IDE\devenv.com" cglm.sln /Upgrade + + - name: Set SIMD flags + run: | + if ($Env:SIMD -eq 'none') { + $Env:CFLAGS="" + } elseif ($Env:SIMD -eq 'sse') { + $Env:CFLAGS="-arch:SSE" + } elseif ($Env:SIMD -eq 'sse2') { + $Env:CFLAGS="-arch:SSE2" + } elseif ($Env:SIMD -eq 'sse3') { + $Env:CFLAGS="-arch:SSE3" + } elseif ($Env:SIMD -eq 'sse4') { + $Env:CFLAGS="-arch:SSE4" + } elseif ($Env:SIMD -eq 'avx') { + $Env:CFLAGS="-arch:AVX" + } elseif ($Env:SIMD -eq 'avx2') { + $Env:CFLAGS="-arch:AVX2" + } elseif ($Env:SIMD -eq 'neon') { + $Env:CFLAGS="-arch:NEON" + } + + - name: Build (x86) + working-directory: win + run: msbuild cglm.vcxproj /p:Configuration=Release /p:Platform=x86 /p:PlatformToolset=v143 /p:BuildInParallel=true /p:AdditionalOptions="$Env:CFLAGS" + + - name: Build (x64) + working-directory: win + run: msbuild cglm.vcxproj /p:Configuration=Release /p:Platform=x64 /p:PlatformToolset=v143 /p:BuildInParallel=true /p:AdditionalOptions="$Env:CFLAGS" build_documentation: name: Documentation @@ -176,57 +401,13 @@ jobs: working-directory: docs run: sphinx-build -W --keep-going source build - build_meson: - name: Meson / ${{ matrix.os }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [macos-14, ubuntu-22.04] - - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v5 - with: - python-version: '3.12' - cache: 'pip' - - - name: Install meson - run: python3 -m pip install meson ninja - - - name: Build - run: meson setup build -Dbuildtype=release --default-library=static -Dbuild_tests=true - - - name: Test - run: meson test -C build - - build_msbuild: - name: MSBuild / Windows - runs-on: windows-2022 - - # This has no test yet. - # It could also try building for ARM, ARM64, ARM64EC, but those fail currently. - steps: - - uses: actions/checkout@v4 - - - uses: microsoft/setup-msbuild@v2 - - - name: Build (x86) - working-directory: win - run: msbuild cglm.vcxproj /p:Configuration=Release /p:Platform=x86 /p:BuildInParallel=true - - - name: Build (x64) - working-directory: win - run: msbuild cglm.vcxproj /p:Configuration=Release /p:Platform=x64 /p:BuildInParallel=true - build_swift: name: Swift ${{ matrix.swift }} / ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: [macos-12, macos-14, ubuntu-22.04] + os: [macos-13, macos-14, ubuntu-22.04] # This has no test yet. steps: diff --git a/.github/workflows/cmake-wasm.yml b/.github/workflows/cmake-wasm.yml index 66039b2..cdccaa6 100644 --- a/.github/workflows/cmake-wasm.yml +++ b/.github/workflows/cmake-wasm.yml @@ -31,10 +31,20 @@ jobs: wget --no-verbose https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${{matrix.wasi_sdk_version}}/wasi-sdk-${{matrix.wasi_sdk_version}}.0-linux.tar.gz tar xf wasi-sdk-${{matrix.wasi_sdk_version}}.0-linux.tar.gz + # Building a wasm library without needing to define a main(): + # https://github.com/WebAssembly/wasi-sdk/issues/332 + - name: Modify CMakeLists.txt for WASI + run: | + echo 'if (CMAKE_SYSTEM_NAME STREQUAL "WASI")' >> CMakeLists.txt + echo ' target_link_options(${PROJECT_NAME} PRIVATE -mexec-model=reactor)' >> CMakeLists.txt + echo 'endif()' >> CMakeLists.txt + - name: Configure CMake # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type - run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{matrix.BUILD_TYPE}} -DCMAKE_C_FLAGS="${{matrix.C_FLAGS}}" -DCMAKE_TOOLCHAIN_FILE=${{github.workspace}}/wasi-sdk-${{matrix.wasi_sdk_version}}.0/share/cmake/wasi-sdk.cmake -DWASI_SDK_PREFIX=${{github.workspace}}/wasi-sdk-${{matrix.wasi_sdk_version}}.0 -DCGLM_USE_TEST=ON + # Below suppress <<'clock' is deprecated: WASI lacks process-associated clocks; ...>> warns: + # -D_WASI_EMULATED_PROCESS_CLOCKS" -DCMAKE_EXE_LINKER_FLAGS="-lwasi-emulated-process-clocks + run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{matrix.BUILD_TYPE}} -DCMAKE_C_FLAGS="${{matrix.C_FLAGS}} -D_WASI_EMULATED_PROCESS_CLOCKS" -DCMAKE_EXE_LINKER_FLAGS="-lwasi-emulated-process-clocks" -DCMAKE_TOOLCHAIN_FILE=${{github.workspace}}/wasi-sdk-${{matrix.wasi_sdk_version}}.0/share/cmake/wasi-sdk.cmake -DWASI_SDK_PREFIX=${{github.workspace}}/wasi-sdk-${{matrix.wasi_sdk_version}}.0 -DCGLM_STATIC=ON -DCGLM_SHARED=OFF -DCGLM_USE_TEST=ON - name: Build # Build your program with the given configuration diff --git a/.gitignore b/.gitignore index 8063137..879f459 100644 --- a/.gitignore +++ b/.gitignore @@ -80,3 +80,4 @@ confdefs.h cmake-build-debug *.o.tmp xcode/* +.vscode \ No newline at end of file diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index e69de29..0000000 diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json deleted file mode 100644 index 7136a9e..0000000 --- a/.vscode/c_cpp_properties.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "configurations": [ - { - "name": "Mac", - "includePath": [ - "${workspaceFolder}/**" - ], - "defines": [], - "macFrameworkPath": [ - "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks" - ], - "compilerPath": "/usr/bin/clang", - "cStandard": "c23", - "cppStandard": "c++23", - "intelliSenseMode": "macos-clang-arm64", - "configurationProvider": "vector-of-bool.cmake-tools" - } - ], - "version": 4 -} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index e4a6b4f..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "C_Cpp.default.configurationProvider": "vector-of-bool.cmake-tools", - "restructuredtext.confPath": "${workspaceFolder}/docs/source", - "workbench.colorTheme": "Default Light+ Experimental", - "editor.fontSize": 14, - "workbench.colorCustomizations": { - "[Default Light*]": { - "editor.background": "#fefefe", - "sideBar.background": "#fefefe", - "sideBar.foreground": "#343436", - "sideBarTitle.foreground": "#343436", - "sideBar.border": "#e2e2e4", - "statusBar.background": "#fefefe", - "titleBar.activeBackground": "#fefefe", - "tab.activeBackground": "#f4fff4aa", - "tab.inactiveBackground": "#fefefe", - "activityBar.background": "#fefefe", - "editorGroupHeader.tabsBackground": "#fefefe" - }, - "[Default Dark*]": { - "editor.background": "#1D1D25", - "sideBar.background": "#1D1D25", - "statusBar.background": "#1D1D25", - "titleBar.activeBackground": "#1D1D25", - "tab.activeBackground": "#2C2C3A", - "tab.inactiveBackground": "#1D1D25", - "activityBar.background": "#1D1D25", - "editorGroupHeader.tabsBackground": "#1D1D25" - } - }, -} \ No newline at end of file diff --git a/BUILDING.md b/BUILDING.md new file mode 100644 index 0000000..01452f5 --- /dev/null +++ b/BUILDING.md @@ -0,0 +1,199 @@ +# Building the library + +cglm can be built using one of the following build systems: + +## CMake (All platforms) +```bash +$ mkdir build +$ cd build +$ cmake .. # [Optional] -DCGLM_SHARED=ON +$ make +$ sudo make install # [Optional] +``` + +### Options with defaults + +```CMake +option(CGLM_SHARED "Shared build" ON) +option(CGLM_STATIC "Static build" OFF) +option(CGLM_USE_C99 "" OFF) #Β C11 +option(CGLM_USE_TEST "Enable Tests" OFF) #Β for make check - make test +``` + +### Including in a CMake project + +#### Header only + +This requires no building or installation of cglm. + +* Example: + +``` cmake +cmake_minimum_required(VERSION 3.8.2) + +project() + +add_executable(${PROJECT_NAME} src/main.c) +target_link_libraries(${LIBRARY_NAME} PRIVATE + cglm_headers) + +add_subdirectory(external/cglm/ EXCLUDE_FROM_ALL) +``` + +#### Linked + +* Example: +```cmake +cmake_minimum_required(VERSION 3.8.2) + +project() + +add_executable(${PROJECT_NAME} src/main.c) +target_link_libraries(${LIBRARY_NAME} PRIVATE + cglm) + +add_subdirectory(external/cglm/) + +# or you can use find_package to configure cglm +``` + +### Using CMake to build for WebAssembly + +Since math functions like `sinf` are used, this can not be targeted at `wasm32-unknown-unknown`, one of [wasi-sdk](https://github.com/WebAssembly/wasi-sdk) or [emscripten](https://github.com/emscripten-core/emsdk) should be used. + +Should note that shared build is not yet supported for WebAssembly. + +For [simd128](https://github.com/WebAssembly/simd) support, add `-msimd128` to `CMAKE_C_FLAGS`, in command line `-DCMAKE_C_FLAGS="-msimd128"`. + +For tests, the cmake option `CGLM_USE_TEST` would still work, you'll need a wasi runtime for running tests, see our [ci config file](.github/workflows/cmake-wasm.yml) for a detailed example. + +#### WASI SDK + +```bash +$ cmake .. \ + -DCMAKE_TOOLCHAIN_FILE=/path/to/wasi-sdk-19.0/share/cmake/wasi-sdk.cmake \ + -DWASI_SDK_PREFIX=/path/to/wasi-sdk-19.0 +``` + +Where `/path/to/wasi-sdk-19.0/` is the path to extracted [wasi sdk](https://github.com/WebAssembly/wasi-sdk). + +In this case it would by default make a static build. + +#### Emscripten + +```bash +$ emcmake cmake .. \ + -DCMAKE_EXE_LINKER_FLAGS="-s STANDALONE_WASM" \ + -DCGLM_STATIC=ON +``` + +The `emcmake` here is the cmake wrapper for Emscripten from installed [emsdk](https://github.com/emscripten-core/emsdk). + +## Meson (All platforms) + +```bash +$ meson build # [Optional] --default-library=static +$ cd build +$ ninja +$ sudo ninja install # [Optional] +``` + +### Options with Defaults: + +```meson +c_std=c11 +buildtype=release +default_library=shared +build_tests=true #Β to run tests: ninja test +``` +### Including in a Meson project +* Example: +```meson +# Clone cglm or create a cglm.wrap under /subprojects +project('name', 'c') + +cglm_dep = dependency('cglm', fallback : 'cglm', 'cglm_dep') + +executable('exe', 'src/main.c', dependencies : cglm_dep) +``` + +## Swift (Swift Package Manager) + +Currently only default build options are supported. Add **cglm** dependency to your project: + +```swift +... +Package( + ... + dependencies: [ + ... + .package(url: "https://github.com/recp/cglm", .branch("master")), + ] + ... +) +``` + +Now add **cgml** as a dependency to your target. Product choices are: +- **cglm** for inlined version of the library which can be linked only statically +- **cglmc** for a compiled version of the library with no linking limitation + +```swift +... +.target( + ... + dependencies: [ + ... + .product(name: "cglm", package: "cglm"), + ] + ... +) +... +``` + +## Unix (Autotools) + +```bash +$ sh autogen.sh +$ ./configure +$ make +$ make check # [Optional] +$ [sudo] make install # [Optional] +``` + +This will also install pkg-config files so you can use +`pkg-config --cflags cglm` and `pkg-config --libs cglm` to retrieve compiler +and linker flags. + +The files will be installed into the given prefix (usually `/usr/local` by +default on Linux), but your pkg-config may not be configured to actually check +there. You can figure out where it's looking by running `pkg-config --variable +pc_path pkg-config` and change the path the files are installed to via +`./configure --with-pkgconfigdir=/your/path`. Alternatively, you can add the +prefix path to your `PKG_CONFIG_PATH` environment variable. + +## Windows (MSBuild) +Windows related build file and project files are located in `win` folder, +make sure you are inside `cglm/win` folder. +Code Analysis is enabled, so it may take awhile to build. + +```Powershell +$ cd win +$ .\build.bat +``` +if `msbuild` won't work (because of multi version VS) then try to build with `devenv`: +```Powershell +$ devenv cglm.sln /Build Release +``` + +### Running Tests on Windows + +You can see test project in same visual studio solution file. It is enough to run that project to run tests. + +# Building the documentation +First you need install Sphinx: http://www.sphinx-doc.org/en/master/usage/installation.html +then: +```bash +$ cd docs +$ sphinx-build source build +``` +it will compile docs into build folder, you can run index.html inside that function. \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 169296d..a331595 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.8.2) +cmake_minimum_required(VERSION 3.13) project(cglm VERSION 0.9.5 HOMEPAGE_URL https://github.com/recp/cglm @@ -93,8 +93,10 @@ add_library(${PROJECT_NAME} src/mat4x2.c src/mat4x3.c src/plane.c + src/noise.c src/frustum.c src/box.c + src/aabb2d.c src/project.c src/sphere.c src/ease.c diff --git a/Makefile.am b/Makefile.am index 2a8ce0e..2b4c299 100644 --- a/Makefile.am +++ b/Makefile.am @@ -67,6 +67,7 @@ cglm_HEADERS = include/cglm/version.h \ include/cglm/util.h \ include/cglm/quat.h \ include/cglm/plane.h \ + include/cglm/noise.h \ include/cglm/frustum.h \ include/cglm/box.h \ include/cglm/aabb2d.h \ @@ -120,6 +121,7 @@ cglm_call_HEADERS = include/cglm/call/mat4.h \ include/cglm/call/quat.h \ include/cglm/call/euler.h \ include/cglm/call/plane.h \ + include/cglm/call/noise.h \ include/cglm/call/frustum.h \ include/cglm/call/box.h \ include/cglm/call/project.h \ @@ -210,6 +212,7 @@ cglm_struct_HEADERS = include/cglm/struct/mat4.h \ include/cglm/struct/quat.h \ include/cglm/struct/euler.h \ include/cglm/struct/plane.h \ + include/cglm/struct/noise.h \ include/cglm/struct/frustum.h \ include/cglm/struct/box.h \ include/cglm/struct/aabb2d.h \ @@ -261,6 +264,7 @@ libcglm_la_SOURCES=\ src/mat4x2.c \ src/mat4x3.c \ src/plane.c \ + src/noise.c \ src/frustum.c \ src/box.c \ src/project.c \ @@ -270,6 +274,7 @@ libcglm_la_SOURCES=\ src/bezier.c \ src/ray.c \ src/affine2d.c \ + src/aabb2d.c \ src/clipspace/ortho_lh_no.c \ src/clipspace/ortho_lh_zo.c \ src/clipspace/ortho_rh_no.c \ diff --git a/README.md b/README.md index 08bc3a5..0f02789 100644 --- a/README.md +++ b/README.md @@ -39,73 +39,100 @@

-Highly optimized 2D|3D math library, also known as OpenGL Mathematics (glm) for `C`. cglm provides lot of utils to help math operations to be fast and quick to write. It is community friendly, feel free to bring any issues, bugs you faced. +A highly optimized 2D|3D math library. Also known as OpenGL Mathematics (glm) for C. cglm provides fast and ergonomic math functions to ease graphics programming. It is community friendly – feel free to report any bugs and issues you face.
+If you're using C++, you might want to check out GLM

+ - Allocation-free + - Header-only + - SIMD-optimized + - API-agnostic + --- -#### πŸ“š Documentation +### πŸ“š Documentation -Almost all functions (inline versions) and parameters are documented inside the corresponding headers.
-Complete documentation: http://cglm.readthedocs.io +All functions and their parameters are documented above their declaration inside their corresponding headers.
+Alternatively, you can read the complete documentation [here](http://cglm.readthedocs.io). -#### πŸ“Œ Note for previous versions: +### πŸ”¨ Building -- _dup (duplicate) is changed to _copy. For instance `glm_vec_dup -> glm_vec3_copy` -- OpenGL related functions are dropped to make this lib platform/third-party independent -- make sure you have latest version and feel free to report bugs, troubles -- **[bugfix]** euler angles was implemented in reverse order (extrinsic) it was fixed, now they are intrinsic. Make sure that -you have the latest version -- **[major change]** by starting v0.4.0, quaternions are stored as [x, y, z, w], it was [w, x, y, z] in v0.3.5 and earlier versions -- **[api rename]** by starting v0.4.5, **glm_simd** functions are renamed to **glmm_** -- **[new option]** by starting v0.4.5, you can disable alignment requirement, check options in docs. -- **[major change]** by starting v0.5.0, vec3 functions use **glm_vec3_** namespace, it was **glm_vec_** until v0.5.0 -- **[major change]** by starting v0.5.1, built-in alignment is removed from **vec3** and **mat3** types -- **[major change]** by starting v0.7.3, inline print functions are disabled in release/production mode to eliminate print costs (see options in documentation). Print output also improved. You can disable colors if you need (see documentation) -- **[major change]** by starting v0.8.3, **cglm** supports alternative clipspace configurations e.g. Left Handed, Zero-to-One (_zo)... `CGLM_FORCE_DEPTH_ZERO_TO_ONE` and `CGLM_FORCE_LEFT_HANDED` is provided to control clipspace. You should be able to use **cglm** with Vulkan, DirectX and Metal now... see https://cglm.readthedocs.io/en/latest/opt.html#clipspace-option-s +cglm can be used in it's entirety as a header-only library simply by including `cglm/cglm.h`. If you wish to link against it instead, it can be built using one of the supported build systems. Detailed information about building on individual platforms and build systems along with the instructions for building the documentation can be found in [BUILDING.md](./BUILDING.md). -#### πŸ“Œ Note for C++ developers: -If you are not aware of the original GLM library yet, you may also want to look at: -https://github.com/g-truc/glm +### βœ… Usage -#### πŸ“Œ Note for new comers (Important): -- `vec4` and `mat4` variables must be aligned. (There will be unaligned versions later) -- **in** and **[in, out]** parameters must be initialized (please). But **[out]** parameters not, initializing out param is also redundant -- All functions are inline if you don't want to use pre-compiled versions with glmc_ prefix, you can ignore build process. Just include headers. -- if your debugger takes you to cglm headers then make sure you are not trying to copy vec4 to vec3 or alig issues... -- Welcome! +#### Header-only -#### πŸ“Œ Note for experienced developers: -- Since I'm testing this library in my projects, sometimes bugs occurs; finding that bug[s] and making improvements would be more easy with multiple developer/contributor and their projects or knowledge. Consider to make some tests if you suspect something is wrong and any feedbacks, contributions and bug reports are always welcome. +Include the `cglm/cglm.h` header and use functions with the `glm_` prefix. +```c +#include "cglm/cglm.h" -#### πŸ“Œ Allocations? -`cglm` doesn't alloc any memory on heap. So it doesn't provide any allocator. You should alloc memory for **out** parameters too if you pass pointer of memory location. Don't forget that **vec4** (also quat/**versor**) and **mat4** must be aligned (16-bytes), because *cglm* uses SIMD instructions to optimize most operations if available. +// ... -#### πŸ“Œ Returning vector or matrix... ? +vec2 vector; +glm_vec2_zero(vector); +``` -**cglm** supports both *ARRAY API* and *STRUCT API*, so you can return structs if you utilize struct api (`glms_`). +#### Struct API -
+Include `cglm/struct.h` and use `glms_`. +```c +#include "cglm/struct.h" - - - - - - - -
-
Like some other graphics libraries (especially OpenGL) this library use Column-Major layout to keep matrices in the memory.
-
 
-
In the future the library may support an option to use row-major layout, CURRENTLY if you need to row-major layout you will need to transpose it.
-
- -
+// ... -## πŸš€ Features -- **scalar** and **simd** (sse, avx, neon...) optimizations -- option to use different clipspaces e.g. Left Handed, Zero-to-One... (currently right handed negative-one is default) -- array api and struct api, you can use arrays or structs. +vec2s vector = glms_vec2_zero(); +``` + +#### Linked + +Include `cglm/call.h` and use `glmc_`. +```c +#include "cglm/call.h" + +// ... + +vec2 vector; +glmc_vec2_zero(vector); +``` + +### ❗ Alignment + +While cglm by default aligns what's necessary, it is possible to disable this by defining `CGLM_ALL_UNALIGNED`. If you're targeting machines with any kind of SIMD support, make sure that all `vec4`, `mat4` and `mat2` arguments you pass to cglm functions are aligned to prevent unexpected crashes, alternatively use the unaligned versions if present. + +### Struct API + +The struct API works as follows (note the `s` suffix on types, `glms_` prefix on functions and `GLMS_` on constants): + +```C +#include + +mat4s mat = GLMS_MAT4_IDENTITY_INIT; +mat4s inv = glms_mat4_inv(mat); +``` + +Struct functions generally take parameters *by copy* and *return* the results rather than taking pointers and writing to out parameters. That means your variables can usually be `const`, if you're into that. + +The types used are actually unions that allow access to the same data in multiple ways. One of these involves anonymous structures available since C11. MSVC supports them in earlier versions out of the box and GCC/Clang as well if you enable `-fms-extensions`. +To explicitly enable anonymous structures `#define CGLM_USE_ANONYMOUS_STRUCT 1`, or `0` to disable them. +For backwards compatibility, you can also `#define CGLM_NO_ANONYMOUS_STRUCT` to disable them. If you don't specify explicitly, cglm will attempt a best guess based on your compiler and C version. + +### πŸ“Œ Migration notes: + +- `_dup` (duplicate) functions were renamed to `_copy`. For instance: `glm_vec_dup` -> `glm_vec3_copy`. +- OpenGL related functions were dropped to make cglm API independent. +- **[bugfix]** Euler angles had been previously implemented in reverse order (extrinsic). This was fixed to be intrinsic. +- **[major change]** Starting with **v0.4.0**, quaternions are stored as [x, y, z, w]. Previously it was [w, x, y, z]. +- **[api rename]** Starting with **v0.4.5**, `glm_simd_` functions are renamed to `glmm_`. +- **[new option]** Starting with **v0.4.5**, alignment requirements can be disabled. Read more in the documentation. +- **[major change]** Starting with **v0.5.0**, vec3 functions occupy the **glm_vec3_** namespace. This used to be **glm_vec_** in earlier versions. +- **[major change]** Starting with **v0.5.1**, `vec3` and `mat3` types are not aligned by default. +- **[major change]** Starting with **v0.7.3**, inline print functions are disabled by default in release mode to eliminate printing costs (see the Options chapter of the docs).
Colored output can be disabled (see documentation). +- **[major change]** Starting with **v0.8.3**, alternate clipspace configurations are supported. The `CGLM_FORCE_DEPTH_ZERO_TO_ONE` and `CGLM_FORCE_LEFT_HANDED` flags are provided to control clip depth and handedness. This makes it easier to incorporate cglm into projects using graphics APIs such as Vulkan or Metal. See https://cglm.readthedocs.io/en/latest/opt.html#clipspace-option-s + +### πŸš€ Features + +- scalar and simd (sse, avx, neon...) optimizations - general purpose matrix operations (mat4, mat3) - chain matrix multiplication (square only) - general purpose vector operations (cross, dot, rotate, proj, angle...) @@ -117,49 +144,35 @@ https://github.com/g-truc/glm - quaternions - euler angles / yaw-pitch-roll to matrix - extract euler angles -- inline or pre-compiled function call - frustum (extract view frustum planes, corners...) - bounding box (AABB in Frustum (culling), crop, merge...) - bounding sphere - project, unproject - easing functions - curves -- curve interpolation helpers (S*M*C, deCasteljau...) -- helpers to convert cglm types to Apple's simd library to pass cglm types to Metal GL without packing them on both sides +- curve interpolation helpers (SMC, deCasteljau...) +- comversion helpers from cglm types to Apple's simd library to pass cglm types to Metal GL without packing them on both sides - ray intersection helpers -- and others... +--- -
+ + + + + + + +
+
Like other graphics libraries (especially OpenGL), cglm uses column-major layout to keep matrices in memory.
+
 
+
While we might support row-major matrices in the future, currently if you need your matrices to be in row-major layout you have to transpose them.
+
+ +
-You have two options to call a function/operation: inline or library call (link) -Almost all functions are marked inline (always_inline) so compiler will probably inline. -To call pre-compiled versions, just use `glmc_` (c stands for 'call') instead of `glm_`. +--- -```C - #include /* for inline */ - #include /* for library call (this also includes cglm.h) */ - - mat4 rot, trans, rt; - /* ... */ - glm_mul(trans, rot, rt); /* inline */ - glmc_mul(trans, rot, rt); /* call from library */ -``` -Most of math functions are optimized manually with SSE2 if available, if not? Dont worry there are non-sse versions of all operations - -You can pass matrices and vectors as array to functions rather than get address. - -```C - mat4 m = { - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - }; - - glm_translate(m, (vec3){1.0f, 0.0f, 0.0f}); -``` - -Library contains general purpose mat4 mul and inverse functions, and also contains some special forms (optimized) of these functions for affine transformations' matrices. If you want to multiply two affine transformation matrices you can use glm_mul instead of glm_mat4_mul and glm_inv_tr (ROT + TR) instead glm_mat4_inv +cglm contains general purpose mat4 product and inverse functions but also provides optimized versions for affine transformations. If you want to multiply two affine transformation matrices you can use glm_mul instead of glm_mat4_mul and glm_inv_tr (ROT + TR) instead glm_mat4_inv. ```C /* multiplication */ mat4 modelMat; @@ -169,311 +182,9 @@ glm_mul(T, R, modelMat); glm_inv_tr(modelMat); ``` -### Struct API - -The struct API works as follows, note the `s` suffix on types, the `glms_` prefix on functions and the `GLMS_` prefix on constants: - -```C -#include - -mat4s mat = GLMS_MAT4_IDENTITY_INIT; -mat4s inv = glms_mat4_inv(mat); -``` - -Struct functions generally take their parameters as *values* and *return* their results, rather than taking pointers and writing to out parameters. That means your parameters can usually be `const`, if you're into that. - -The types used are actually unions that allow access to the same data multiple ways. One of those ways involves anonymous structures, available since C11. MSVC also supports it for earlier C versions out of the box and GCC/Clang do if you enable `-fms-extensions`. To explicitly enable these anonymous structures, `#define CGLM_USE_ANONYMOUS_STRUCT` to `1`, to disable them, to `0`. For backward compatibility, you can also `#define CGLM_NO_ANONYMOUS_STRUCT` (value is irrelevant) to disable them. If you don't specify explicitly, cglm will do a best guess based on your compiler and the C version you're using. - -## πŸ”¨ Build - -### CMake (All platforms) -```bash -$ mkdir build -$ cd build -$ cmake .. # [Optional] -DCGLM_SHARED=ON -$ make -$ sudo make install # [Optional] -``` - -##### Cmake options with Defaults: - -```CMake -option(CGLM_SHARED "Shared build" ON) -option(CGLM_STATIC "Static build" OFF) -option(CGLM_USE_C99 "" OFF) #Β C11 -option(CGLM_USE_TEST "Enable Tests" OFF) #Β for make check - make test -``` - -#### Use as header-only library with your CMake project - -This requires no building or installation of cglm. - -* Example: - -``` cmake -cmake_minimum_required(VERSION 3.8.2) - -project() - -add_executable(${PROJECT_NAME} src/main.c) -target_link_libraries(${LIBRARY_NAME} PRIVATE - cglm_headers) - -add_subdirectory(external/cglm/ EXCLUDE_FROM_ALL) -``` - -#### Use with your CMake project -* Example: -```cmake -cmake_minimum_required(VERSION 3.8.2) - -project() - -add_executable(${PROJECT_NAME} src/main.c) -target_link_libraries(${LIBRARY_NAME} PRIVATE - cglm) - -add_subdirectory(external/cglm/) - -# or you can use find_package to configure cglm -``` - -#### Use CMake to build for WebAssembly - -Since math functions like `sinf` is used, this can not be targeted at `wasm32-unknown-unknown`, one of [wasi-sdk](https://github.com/WebAssembly/wasi-sdk) or [emscripten](https://github.com/emscripten-core/emsdk) should be used. - -Should note that shared build is not yet supported for WebAssembly. - -For [simd128](https://github.com/WebAssembly/simd) support, add `-msimd128` to `CMAKE_C_FLAGS`, in command line `-DCMAKE_C_FLAGS="-msimd128"`. - -For tests, the cmake option `CGLM_USE_TEST` would still work, you'll need a wasi runtime for running tests, see our [ci config file](.github/workflows/cmake-wasm.yml) for a detailed example. - -##### Use CMake and WASI SDK to build for WebAssembly - -```bash -$ cmake .. \ - -DCMAKE_TOOLCHAIN_FILE=/path/to/wasi-sdk-19.0/share/cmake/wasi-sdk.cmake \ - -DWASI_SDK_PREFIX=/path/to/wasi-sdk-19.0 -``` - -Where `/path/to/wasi-sdk-19.0/` is the path to extracted [wasi sdk](https://github.com/WebAssembly/wasi-sdk). - -In this case it would by default make a static build. - -##### Use CMake and Emscripten SDK to build for WebAssembly - -```bash -$ emcmake cmake .. \ - -DCMAKE_EXE_LINKER_FLAGS="-s STANDALONE_WASM" \ - -DCGLM_STATIC=ON -``` - -The `emcmake` here is the cmake wrapper for Emscripten from installed [emsdk](https://github.com/emscripten-core/emsdk). - -### Meson (All platforms) - -```bash -$ meson build # [Optional] --default-library=static -$ cd build -$ ninja -$ sudo ninja install # [Optional] -``` - -##### Meson options with Defaults: - -```meson -c_std=c11 -buildtype=release -default_library=shared -build_tests=true #Β to run tests: ninja test -``` -#### Use with your Meson project -* Example: -```meson -# Clone cglm or create a cglm.wrap under /subprojects -project('name', 'c') - -cglm_dep = dependency('cglm', fallback : 'cglm', 'cglm_dep') - -executable('exe', 'src/main.c', dependencies : cglm_dep) -``` - -### Swift (Swift Package Manager) - -Currently only default build options are supported. Add **cglm** dependency to your project: - -```swift -... -Package( - ... - dependencies: [ - ... - .package(url: "https://github.com/recp/cglm", .branch("master")), - ] - ... -) -``` - -Now add **cgml** as a dependency to your target. Product choices are: -- **cglm** for inlined version of the library which can be linked only statically -- **cglmc** for a compiled version of the library with no linking limitation - -```swift -... -.target( - ... - dependencies: [ - ... - .product(name: "cglm", package: "cglm"), - ] - ... -) -... -``` - -### Unix (Autotools) - -```bash -$ sh autogen.sh -$ ./configure -$ make -$ make check # [Optional] -$ [sudo] make install # [Optional] -``` - -This will also install pkg-config files so you can use -`pkg-config --cflags cglm` and `pkg-config --libs cglm` to retrieve compiler -and linker flags. - -The files will be installed into the given prefix (usually `/usr/local` by -default on Linux), but your pkg-config may not be configured to actually check -there. You can figure out where it's looking by running `pkg-config --variable -pc_path pkg-config` and change the path the files are installed to via -`./configure --with-pkgconfigdir=/your/path`. Alternatively, you can add the -prefix path to your `PKG_CONFIG_PATH` environment variable. - -### Windows (MSBuild) -Windows related build file and project files are located in `win` folder, -make sure you are inside `cglm/win` folder. -Code Analysis is enabled, so it may take awhile to build. - -```Powershell -$ cd win -$ .\build.bat -``` -if `msbuild` won't work (because of multi version VS) then try to build with `devenv`: -```Powershell -$ devenv cglm.sln /Build Release -``` - -#### Running Tests on Windows - -You can see test project in same visual studio solution file. It is enough to run that project to run tests. - -### Building Docs -First you need install Sphinx: http://www.sphinx-doc.org/en/master/usage/installation.html -then: -```bash -$ cd docs -$ sphinx-build source build -``` -it will compile docs into build folder, you can run index.html inside that function. - -## How to use -If you want to use the inline versions of functions, then include the main header -```C -#include -``` -the header will include all headers. Then call the func you want e.g. rotate vector by axis: -```C -glm_vec3_rotate(v1, glm_rad(45), (vec3){1.0f, 0.0f, 0.0f}); -``` -some functions are overloaded :) e.g you can normalize vector: -```C -glm_vec3_normalize(vec); -``` -this will normalize vec and store normalized vector into `vec` but if you will store normalized vector into another vector do this: -```C -glm_vec3_normalize_to(vec, result); -``` -like this function you may see `_to` postfix, this functions store results to another variables and save temp memory - - -to call pre-compiled versions include header with `c` postfix, c means call. Pre-compiled versions are just wrappers. -```C -#include -``` -this header will include all headers with c postfix. You need to call functions with c posfix: -```C -glmc_vec3_normalize(vec); -``` - -Function usage and parameters are documented inside related headers. You may see same parameter passed twice in some examples like this: -```C -glm_mat4_mul(m1, m2, m1); - -/* or */ -glm_mat4_mul(m1, m1, m1); -``` -the first two parameter are **[in]** and the last one is **[out]** parameter. After multiplying *m1* and *m2*, the result is stored in *m1*. This is why we send *m1* twice. You may store the result in a different matrix, this is just an example. - -### Example: Computing MVP matrix - -#### Option 1 -```C -mat4 proj, view, model, mvp; - -/* init proj, view and model ... */ - -glm_mat4_mul(proj, view, viewProj); -glm_mat4_mul(viewProj, model, mvp); -``` - -#### Option 2 -```C -mat4 proj, view, model, mvp; - -/* init proj, view and model ... */ - -glm_mat4_mulN((mat4 *[]){&proj, &view, &model}, 3, mvp); -``` - -## How to send matrix to OpenGL - -mat4 is array of vec4 and vec4 is array of floats. `glUniformMatrix4fv` functions accecpts `float*` as `value` (last param), so you can cast mat4 to float* or you can pass first column of matrix as beginning of memory of matrix: - -Option 1: Send first column -```C -glUniformMatrix4fv(location, 1, GL_FALSE, matrix[0]); - -/* array of matrices */ -glUniformMatrix4fv(location, 1, GL_FALSE, matrix[0][0]); -``` - -Option 2: Cast matrix to pointer type (also valid for multiple dimensional arrays) -```C -glUniformMatrix4fv(location, 1, GL_FALSE, (float *)matrix); -``` - -You can pass matrices the same way to other APIs e.g. Vulkan, DX... - -## Notes - -- This library does not support double type... yet -- If headers are not working properly with your compiler, IDE please open an issue, because I'm using GCC and clang to test it maybe sometimes MSVC - -**TODO:** -- [ ] Unit tests (In Progress) -- [ ] Unit tests for comparing cglm with glm results -- [x] Add version info -- [ ] Unaligned operations (e.g. `glm_umat4_mul`) -- [x] Extra documentation -- [x] ARM Neon Arch - - ## Contributors -This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. +This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)] @@ -498,6 +209,3 @@ Support this project by becoming a sponsor. Your logo will show up here with a l - -## License -MIT. check the LICENSE file diff --git a/docs/source/aabb2d.rst b/docs/source/aabb2d.rst index ec6bd42..16d18c6 100644 --- a/docs/source/aabb2d.rst +++ b/docs/source/aabb2d.rst @@ -82,7 +82,7 @@ Functions documentation | crops a bounding box with another one. - this could be useful for gettng a bbox which fits with view frustum and + this could be useful for getting a bbox which fits with view frustum and object bounding boxes. In this case you crop view frustum box with objects box @@ -95,7 +95,7 @@ Functions documentation | crops a bounding box with another one. - this could be useful for gettng a bbox which fits with view frustum and + this could be useful for getting a bbox which fits with view frustum and object bounding boxes. In this case you crop view frustum box with objects box diff --git a/docs/source/affine-pre.rst b/docs/source/affine-pre.rst index 35e2c3a..c313fc9 100644 --- a/docs/source/affine-pre.rst +++ b/docs/source/affine-pre.rst @@ -117,7 +117,7 @@ Functions documentation If you need to rotate object around itself e.g. center of object or at some point [of object] then `glm_rotate_at()` would be better choice to do so. - Even if object's model transform is identiy, rotation may not be around + Even if object's model transform is identity, rotation may not be around center of object if object does not lay out at ORIGIN perfectly. Using `glm_rotate_at()` with center of bounding shape ( AABB, Sphere ... ) diff --git a/docs/source/api_inline_array.rst b/docs/source/api_inline_array.rst index 5d8ead8..f989bfe 100644 --- a/docs/source/api_inline_array.rst +++ b/docs/source/api_inline_array.rst @@ -66,6 +66,7 @@ Follow the :doc:`build` documentation for this ivec4 color plane + noise project util io diff --git a/docs/source/api_struct.rst b/docs/source/api_struct.rst index 077e8de..f3e4e78 100644 --- a/docs/source/api_struct.rst +++ b/docs/source/api_struct.rst @@ -9,7 +9,7 @@ By default struct api adds `s` suffix to every type name e.g. vec3s, mat4s, vers Also struct api `s` suffix to namespace e.g. `glms_vec3_add`, `glms_mat4_mul` etc. By starting v0.9.0, struct api namespace is configurable. We can omit **glms_** namespace or -even change it with custom name to move existing api integrations to **cglm** more easliy... +even change it with custom name to move existing api integrations to **cglm** more easily... We can also add **s** to function names if we want e.g. `glms_vec3_add()` -> `vec3_add()` or `vec3s_add()`. By including **cglm/struct.h** header you will include all struct api. It will also include **cglm/cglm.h** too. diff --git a/docs/source/box.rst b/docs/source/box.rst index 76e0822..57632d9 100644 --- a/docs/source/box.rst +++ b/docs/source/box.rst @@ -62,7 +62,7 @@ Functions documentation | crops a bounding box with another one. - this could be useful for gettng a bbox which fits with view frustum and + this could be useful for getting a bbox which fits with view frustum and object bounding boxes. In this case you crop view frustum box with objects box @@ -75,7 +75,7 @@ Functions documentation | crops a bounding box with another one. - this could be useful for gettng a bbox which fits with view frustum and + this could be useful for getting a bbox which fits with view frustum and object bounding boxes. In this case you crop view frustum box with objects box diff --git a/docs/source/noise.rst b/docs/source/noise.rst new file mode 100644 index 0000000..0976eee --- /dev/null +++ b/docs/source/noise.rst @@ -0,0 +1,60 @@ +.. default-domain:: C + +perlin +================================================================================ + +Header: cglm/noise.h + +Classic Perlin noise implementation. + +Based on the work of Stefan Gustavson and Ashima Arts on "webgl-noise": +https://github.com/stegu/webgl-noise +Following Stefan Gustavson's paper "Simplex noise demystified": +http://www.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf + +Implementation based on glm::perlin function: +https://github.com/g-truc/glm/blob/master/glm/gtc/noise.inl + +Table of contents (click to go): +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Functions: + +1. :c:func:`glm_perlin_vec4` +#. :c:func:`glm_perlin_vec3` +#. :c:func:`glm_perlin_vec2` + + +Functions documentation +~~~~~~~~~~~~~~~~~~~~~~~ + +.. c:function:: float glm_perlin_vec4(vec4 point) + + | Classic Perlin noise + + Parameters: + | *[in]* **point** 4D point + + Returns: + | noise value + + +.. c:function:: float glm_perlin_vec3(vec3 point) + + | Classic Perlin noise + + Parameters: + | *[in]* **point** 3D point + + Returns: + | noise value + +.. c:function:: float glm_perlin_vec2(vec2 point) + + | Classic Perlin noise + + Parameters: + | *[in]* **point** 2D point + + Returns: + | noise value diff --git a/docs/source/quat.rst b/docs/source/quat.rst index c52a235..eb6f987 100644 --- a/docs/source/quat.rst +++ b/docs/source/quat.rst @@ -11,9 +11,9 @@ Header: cglm/quat.h What you can do with quaternions with existing functions is (Some of them): -- You can rotate transform matrix using quaterion -- You can rotate vector using quaterion -- You can create view matrix using quaterion +- You can rotate transform matrix using quaternion +- You can rotate vector using quaternion +- You can create view matrix using quaternion - You can create a lookrotation (from source point to dest) Table of contents (click to go): @@ -55,6 +55,7 @@ Functions: #. :c:func:`glm_quat_lerp` #. :c:func:`glm_quat_nlerp` #. :c:func:`glm_quat_slerp` +#. :c:func:`glm_quat_slerp_longest` #. :c:func:`glm_quat_look` #. :c:func:`glm_quat_for` #. :c:func:`glm_quat_forp` @@ -351,6 +352,17 @@ Functions documentation | *[in]* **t** interpolant (amount) clamped between 0 and 1 | *[out]* **dest** result quaternion +.. c:function:: void glm_quat_slerp_longest(versor q, versor r, float t, versor dest) + + | interpolates between two quaternions + | using spherical linear interpolation (SLERP) and always takes the longest path + + Parameters: + | *[in]* **from** from + | *[in]* **to** to + | *[in]* **t** interpolant (amount) clamped between 0 and 1 + | *[out]* **dest** result quaternion + .. c:function:: void glm_quat_look(vec3 eye, versor ori, mat4 dest) | creates view matrix using quaternion as camera orientation diff --git a/docs/source/vec2-ext.rst b/docs/source/vec2-ext.rst index f8d8fe5..70ef4f6 100644 --- a/docs/source/vec2-ext.rst +++ b/docs/source/vec2-ext.rst @@ -27,6 +27,8 @@ Functions: #. :c:func:`glm_vec2_isvalid` #. :c:func:`glm_vec2_sign` #. :c:func:`glm_vec2_abs` +#. :c:func:`glm_vec2_fract` +#. :c:func:`glm_vec2_floor` #. :c:func:`glm_vec2_sqrt` Functions documentation @@ -134,6 +136,22 @@ Functions documentation | *[in]* **v** vector | *[out]* **dest** destination vector +.. c:function:: void glm_vec2_fract(vec2 v, vec2 dest) + + get fractional part of each vector item + + Parameters: + | *[in]* **v** vector + | *[out]* **dest** destination vector + +.. c:function:: void glm_vec2_floor(vec2 v, vec2 dest) + + floor value of each vector item + + Parameters: + | *[in]* **v** vector + | *[out]* **dest** destination vector + .. c:function:: void glm_vec2_sqrt(vec2 v, vec2 dest) square root of each vector item diff --git a/docs/source/vec3-ext.rst b/docs/source/vec3-ext.rst index f99e770..9668932 100644 --- a/docs/source/vec3-ext.rst +++ b/docs/source/vec3-ext.rst @@ -28,6 +28,8 @@ Functions: #. :c:func:`glm_vec3_isvalid` #. :c:func:`glm_vec3_sign` #. :c:func:`glm_vec3_abs` +#. :c:func:`glm_vec3_fract` +#. :c:func:`glm_vec3_floor` #. :c:func:`glm_vec3_sqrt` Functions documentation @@ -151,6 +153,22 @@ Functions documentation | *[in]* **v** vector | *[out]* **dest** destination vector +.. c:function:: void glm_vec3_fract(vec3 v, vec3 dest) + + fractional part of each vector item + + Parameters: + | *[in]* **v** vector + | *[out]* **dest** destination vector + +.. c:function:: void glm_vec3_floor(vec3 v, vec3 dest) + + floor of each vector item + + Parameters: + | *[in]* **v** vector + | *[out]* **dest** destination vector + .. c:function:: void glm_vec3_sqrt(vec3 v, vec3 dest) square root of each vector item diff --git a/docs/source/vec4-ext.rst b/docs/source/vec4-ext.rst index 722424e..bf7eca2 100644 --- a/docs/source/vec4-ext.rst +++ b/docs/source/vec4-ext.rst @@ -23,6 +23,15 @@ Functions: #. :c:func:`glm_vec4_eqv_eps` #. :c:func:`glm_vec4_max` #. :c:func:`glm_vec4_min` +#. :c:func:`glm_vec4_isnan` +#. :c:func:`glm_vec4_isinf` +#. :c:func:`glm_vec4_isvalid` +#. :c:func:`glm_vec4_sign` +#. :c:func:`glm_vec4_abs` +#. :c:func:`glm_vec4_fract` +#. :c:func:`glm_vec4_floor` +#. :c:func:`glm_vec4_sqrt` + Functions documentation ~~~~~~~~~~~~~~~~~~~~~~~ @@ -129,6 +138,30 @@ Functions documentation | *[in]* **v** vector | *[out]* **dest** sign vector (only keeps signs as -1, 0, -1) +.. c:function:: void glm_vec4_abs(vec4 v, vec4 dest) + + absolute value of each vector item + + Parameters: + | *[in]* **v** vector + | *[out]* **dest** destination vector (abs(v)) + +.. c:function:: void glm_vec4_fract(vec4 v, vec4 dest) + + fractional part of each vector item + + Parameters: + | *[in]* **v** vector + | *[out]* **dest** destination vector (fract(v)) + +.. c:function:: void glm_vec4_floor(vec4 v, vec4 dest) + + floor of each vector item + + Parameters: + | *[in]* **v** vector + | *[out]* **dest** destination vector (floor(v)) + .. c:function:: void glm_vec4_sqrt(vec4 v, vec4 dest) square root of each vector item diff --git a/include/cglm/aabb2d.h b/include/cglm/aabb2d.h index b50430c..6369d08 100644 --- a/include/cglm/aabb2d.h +++ b/include/cglm/aabb2d.h @@ -95,7 +95,7 @@ glm_aabb2d_merge(vec2 aabb1[2], vec2 aabb2[2], vec2 dest[2]) { /*! * @brief crops a bounding aabb with another one. * - * this could be useful for gettng a baabb which fits with view frustum and + * this could be useful for getting a baabb which fits with view frustum and * object bounding aabbes. In this case you crop view frustum aabb with objects * aabb * @@ -116,7 +116,7 @@ glm_aabb2d_crop(vec2 aabb[2], vec2 cropAabb[2], vec2 dest[2]) { /*! * @brief crops a bounding aabb with another one. * - * this could be useful for gettng a baabb which fits with view frustum and + * this could be useful for getting a baabb which fits with view frustum and * object bounding aabbes. In this case you crop view frustum aabb with objects * aabb * @@ -268,4 +268,3 @@ glm_aabb2d_contains(vec2 aabb[2], vec2 other[2]) { } #endif /* cglm_aabb2d_h */ - diff --git a/include/cglm/affine-pre.h b/include/cglm/affine-pre.h index f7ccf69..2fa77f7 100644 --- a/include/cglm/affine-pre.h +++ b/include/cglm/affine-pre.h @@ -215,7 +215,7 @@ glm_rotate_z(mat4 m, float angle, mat4 dest) { * If you need to rotate object around itself e.g. center of object or at * some point [of object] then `glm_rotate_at()` would be better choice to do so. * - * Even if object's model transform is identiy, rotation may not be around + * Even if object's model transform is identity, rotation may not be around * center of object if object does not lay out at ORIGIN perfectly. * * Using `glm_rotate_at()` with center of bounding shape ( AABB, Sphere ... ) diff --git a/include/cglm/box.h b/include/cglm/box.h index 8da24f0..8bba678 100644 --- a/include/cglm/box.h +++ b/include/cglm/box.h @@ -75,7 +75,7 @@ glm_aabb_merge(vec3 box1[2], vec3 box2[2], vec3 dest[2]) { /*! * @brief crops a bounding box with another one. * - * this could be useful for gettng a bbox which fits with view frustum and + * this could be useful for getting a bbox which fits with view frustum and * object bounding boxes. In this case you crop view frustum box with objects * box * @@ -98,7 +98,7 @@ glm_aabb_crop(vec3 box[2], vec3 cropBox[2], vec3 dest[2]) { /*! * @brief crops a bounding box with another one. * - * this could be useful for gettng a bbox which fits with view frustum and + * this could be useful for getting a bbox which fits with view frustum and * object bounding boxes. In this case you crop view frustum box with objects * box * diff --git a/include/cglm/call.h b/include/cglm/call.h index de775d2..165f502 100644 --- a/include/cglm/call.h +++ b/include/cglm/call.h @@ -32,6 +32,7 @@ extern "C" { #include "call/quat.h" #include "call/euler.h" #include "call/plane.h" +#include "call/noise.h" #include "call/frustum.h" #include "call/aabb2d.h" #include "call/box.h" diff --git a/include/cglm/call/aabb2d.h b/include/cglm/call/aabb2d.h index 950607e..e6f36a0 100644 --- a/include/cglm/call/aabb2d.h +++ b/include/cglm/call/aabb2d.h @@ -87,5 +87,3 @@ glmc_aabb2d_circle(vec2 aabb[2], vec3 s); } #endif #endif /* cglmc_aabb2d_h */ - - diff --git a/include/cglm/call/box.h b/include/cglm/call/box.h index afb7558..3617eed 100644 --- a/include/cglm/call/box.h +++ b/include/cglm/call/box.h @@ -76,4 +76,3 @@ glmc_aabb_sphere(vec3 box[2], vec4 s); } #endif #endif /* cglmc_box_h */ - diff --git a/include/cglm/call/noise.h b/include/cglm/call/noise.h new file mode 100644 index 0000000..6020c89 --- /dev/null +++ b/include/cglm/call/noise.h @@ -0,0 +1,31 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_noise_h +#define cglmc_noise_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +float +glmc_perlin_vec4(vec4 point); + +CGLM_EXPORT +float +glmc_perlin_vec3(vec3 point); + +CGLM_EXPORT +float +glmc_perlin_vec2(vec2 point); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_noise_h */ diff --git a/include/cglm/call/project.h b/include/cglm/call/project.h index fcfcf2b..8fa7172 100644 --- a/include/cglm/call/project.h +++ b/include/cglm/call/project.h @@ -37,5 +37,3 @@ glmc_pickmatrix(vec2 center, vec2 size, vec4 vp, mat4 dest); } #endif #endif /* cglmc_project_h */ - - diff --git a/include/cglm/call/quat.h b/include/cglm/call/quat.h index acf4313..4244d36 100644 --- a/include/cglm/call/quat.h +++ b/include/cglm/call/quat.h @@ -133,6 +133,10 @@ CGLM_EXPORT void glmc_quat_slerp(versor q, versor r, float t, versor dest); +CGLM_EXPORT +void +glmc_quat_slerp_longest(versor q, versor r, float t, versor dest); + CGLM_EXPORT void glmc_quat_look(vec3 eye, versor ori, mat4 dest); diff --git a/include/cglm/call/vec2.h b/include/cglm/call/vec2.h index 507f042..0284a8c 100644 --- a/include/cglm/call/vec2.h +++ b/include/cglm/call/vec2.h @@ -17,6 +17,18 @@ CGLM_EXPORT void glmc_vec2(float * __restrict v, vec2 dest); +CGLM_EXPORT +void +glmc_vec2_fill(vec2 v, float val); + +CGLM_EXPORT +bool +glmc_vec2_eq(vec2 v, float val); + +CGLM_EXPORT +bool +glmc_vec2_eqv(vec2 a, vec2 b); + CGLM_EXPORT void glmc_vec2_copy(vec2 a, vec2 dest); @@ -177,10 +189,38 @@ CGLM_EXPORT void glmc_vec2_abs(vec2 v, vec2 dest); +CGLM_EXPORT +void +glmc_vec2_fract(vec2 v, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_floor(vec2 v, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_mods(vec2 v, float s, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_swizzle(vec2 v, int mask, vec2 dest); + CGLM_EXPORT void glmc_vec2_lerp(vec2 from, vec2 to, float t, vec2 dest); +CGLM_EXPORT +void +glmc_vec2_step(vec2 edge, vec2 x, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_steps(float edge, vec2 x, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_stepr(vec2 edge, float x, vec2 dest); + CGLM_EXPORT void glmc_vec2_complex_mul(vec2 a, vec2 b, vec2 dest); diff --git a/include/cglm/call/vec3.h b/include/cglm/call/vec3.h index bb5a5d7..640fac7 100644 --- a/include/cglm/call/vec3.h +++ b/include/cglm/call/vec3.h @@ -19,6 +19,7 @@ extern "C" { #define glmc_vec3_flipsign_to(v, dest) glmc_vec3_negate_to(v, dest) #define glmc_vec3_inv(v) glmc_vec3_negate(v) #define glmc_vec3_inv_to(v, dest) glmc_vec3_negate_to(v, dest) +#define glmc_vec3_step_uni(edge, x, dest) glmc_vec3_steps(edge, x, dest); CGLM_EXPORT void @@ -55,7 +56,7 @@ glmc_vec3_norm(vec3 v); CGLM_EXPORT float glmc_vec3_norm2(vec3 v); - + CGLM_EXPORT float glmc_vec3_norm_one(vec3 v); @@ -211,15 +212,15 @@ glmc_vec3_clamp(vec3 v, float minVal, float maxVal); CGLM_EXPORT void glmc_vec3_ortho(vec3 v, vec3 dest); - + CGLM_EXPORT void glmc_vec3_lerp(vec3 from, vec3 to, float t, vec3 dest); - + CGLM_EXPORT void glmc_vec3_lerpc(vec3 from, vec3 to, float t, vec3 dest); - + CGLM_INLINE void glmc_vec3_mix(vec3 from, vec3 to, float t, vec3 dest) { @@ -231,31 +232,31 @@ void glmc_vec3_mixc(vec3 from, vec3 to, float t, vec3 dest) { glmc_vec3_lerpc(from, to, t, dest); } - -CGLM_EXPORT -void -glmc_vec3_step_uni(float edge, vec3 x, vec3 dest); - + CGLM_EXPORT void glmc_vec3_step(vec3 edge, vec3 x, vec3 dest); - + CGLM_EXPORT void glmc_vec3_smoothstep_uni(float edge0, float edge1, vec3 x, vec3 dest); - + CGLM_EXPORT void glmc_vec3_smoothstep(vec3 edge0, vec3 edge1, vec3 x, vec3 dest); - + CGLM_EXPORT void glmc_vec3_smoothinterp(vec3 from, vec3 to, float t, vec3 dest); - + CGLM_EXPORT void glmc_vec3_smoothinterpc(vec3 from, vec3 to, float t, vec3 dest); +CGLM_EXPORT +void +glmc_vec3_swizzle(vec3 v, int mask, vec3 dest); + /* ext */ CGLM_EXPORT @@ -265,7 +266,7 @@ glmc_vec3_mulv(vec3 a, vec3 b, vec3 d); CGLM_EXPORT void glmc_vec3_broadcast(float val, vec3 d); - + CGLM_EXPORT void glmc_vec3_fill(vec3 v, float val); @@ -313,15 +314,31 @@ glmc_vec3_isvalid(vec3 v); CGLM_EXPORT void glmc_vec3_sign(vec3 v, vec3 dest); - + CGLM_EXPORT void glmc_vec3_abs(vec3 v, vec3 dest); - + CGLM_EXPORT void glmc_vec3_fract(vec3 v, vec3 dest); - + +CGLM_EXPORT +void +glmc_vec3_floor(vec3 v, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_mods(vec3 v, float s, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_steps(float edge, vec3 x, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_stepr(vec3 edge, float x, vec3 dest); + CGLM_EXPORT float glmc_vec3_hadd(vec3 v); diff --git a/include/cglm/call/vec4.h b/include/cglm/call/vec4.h index a976e94..22eee24 100644 --- a/include/cglm/call/vec4.h +++ b/include/cglm/call/vec4.h @@ -20,6 +20,7 @@ extern "C" { #define glmc_vec4_flipsign_to(v, dest) glmc_vec4_negate_to(v, dest) #define glmc_vec4_inv(v) glmc_vec4_negate(v) #define glmc_vec4_inv_to(v, dest) glmc_vec4_negate_to(v, dest) +#define glmc_vec4_step_uni(edge, x, dest) glmc_vec4_steps(edge, x, dest) CGLM_EXPORT void @@ -56,7 +57,7 @@ glmc_vec4_norm(vec4 v); CGLM_EXPORT float glmc_vec4_norm2(vec4 v); - + CGLM_EXPORT float glmc_vec4_norm_one(vec4 v); @@ -164,11 +165,11 @@ glmc_vec4_negate(vec4 v); CGLM_EXPORT void glmc_vec4_negate_to(vec4 v, vec4 dest); - + CGLM_EXPORT float glmc_vec4_distance(vec4 a, vec4 b); - + CGLM_EXPORT float glmc_vec4_distance2(vec4 a, vec4 b); @@ -184,15 +185,15 @@ glmc_vec4_minv(vec4 a, vec4 b, vec4 dest); CGLM_EXPORT void glmc_vec4_clamp(vec4 v, float minVal, float maxVal); - + CGLM_EXPORT void glmc_vec4_lerp(vec4 from, vec4 to, float t, vec4 dest); - + CGLM_EXPORT void glmc_vec4_lerpc(vec4 from, vec4 to, float t, vec4 dest); - + CGLM_INLINE void glmc_vec4_mix(vec4 from, vec4 to, float t, vec4 dest) { @@ -204,27 +205,23 @@ void glmc_vec4_mixc(vec4 from, vec4 to, float t, vec4 dest) { glmc_vec4_lerpc(from, to, t, dest); } - -CGLM_EXPORT -void -glmc_vec4_step_uni(float edge, vec4 x, vec4 dest); - + CGLM_EXPORT void glmc_vec4_step(vec4 edge, vec4 x, vec4 dest); - + CGLM_EXPORT void glmc_vec4_smoothstep_uni(float edge0, float edge1, vec4 x, vec4 dest); - + CGLM_EXPORT void glmc_vec4_smoothstep(vec4 edge0, vec4 edge1, vec4 x, vec4 dest); - + CGLM_EXPORT void glmc_vec4_smoothinterp(vec4 from, vec4 to, float t, vec4 dest); - + CGLM_EXPORT void glmc_vec4_smoothinterpc(vec4 from, vec4 to, float t, vec4 dest); @@ -233,6 +230,10 @@ CGLM_EXPORT void glmc_vec4_cubic(float s, vec4 dest); +CGLM_EXPORT +void +glmc_vec4_swizzle(vec4 v, int mask, vec4 dest); + /* ext */ CGLM_EXPORT @@ -242,7 +243,7 @@ glmc_vec4_mulv(vec4 a, vec4 b, vec4 d); CGLM_EXPORT void glmc_vec4_broadcast(float val, vec4 d); - + CGLM_EXPORT void glmc_vec4_fill(vec4 v, float val); @@ -290,15 +291,31 @@ glmc_vec4_isvalid(vec4 v); CGLM_EXPORT void glmc_vec4_sign(vec4 v, vec4 dest); - + CGLM_EXPORT void glmc_vec4_abs(vec4 v, vec4 dest); - + CGLM_EXPORT void glmc_vec4_fract(vec4 v, vec4 dest); - + +CGLM_EXPORT +void +glmc_vec4_floor(vec4 v, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_mods(vec4 v, float s, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_steps(float edge, vec4 x, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_stepr(vec4 edge, float x, vec4 dest); + CGLM_EXPORT float glmc_vec4_hadd(vec4 v); @@ -323,4 +340,3 @@ glmc_vec4_refract(vec4 v, vec4 n, float eta, vec4 dest); } #endif #endif /* cglmc_vec4_h */ - diff --git a/include/cglm/cglm.h b/include/cglm/cglm.h index 5e15a3c..146ded0 100644 --- a/include/cglm/cglm.h +++ b/include/cglm/cglm.h @@ -30,6 +30,7 @@ #include "quat.h" #include "euler.h" #include "plane.h" +#include "noise.h" #include "aabb2d.h" #include "box.h" #include "color.h" diff --git a/include/cglm/common.h b/include/cglm/common.h index af1116f..11588cf 100644 --- a/include/cglm/common.h +++ b/include/cglm/common.h @@ -51,6 +51,7 @@ #define GLM_SHUFFLE4(z, y, x, w) (((z) << 6) | ((y) << 4) | ((x) << 2) | (w)) #define GLM_SHUFFLE3(z, y, x) (((z) << 4) | ((y) << 2) | (x)) +#define GLM_SHUFFLE2(y, x) (((y) << 2) | (x)) #include "types.h" #include "simd/intrin.h" diff --git a/include/cglm/handed/euler_to_quat_lh.h b/include/cglm/handed/euler_to_quat_lh.h index def40c9..1bb350b 100644 --- a/include/cglm/handed/euler_to_quat_lh.h +++ b/include/cglm/handed/euler_to_quat_lh.h @@ -164,4 +164,4 @@ glm_euler_zyx_quat_lh(vec3 angles, versor dest) { dest[3] = zc * yc * xc + zs * ys * xs; } -#endif /*cglm_euler_to_quat_lh_h*/ \ No newline at end of file +#endif /*cglm_euler_to_quat_lh_h*/ diff --git a/include/cglm/io.h b/include/cglm/io.h index b95751b..baa80f1 100644 --- a/include/cglm/io.h +++ b/include/cglm/io.h @@ -132,9 +132,9 @@ glm_mat4_print(mat4 matrix, for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { if (matrix[i][j] < CGLM_PRINT_MAX_TO_SHORT) - cwi = sprintf(buff, "% .*f", CGLM_PRINT_PRECISION, (double)matrix[i][j]); + cwi = snprintf(buff, sizeof(buff), "% .*f", CGLM_PRINT_PRECISION, (double)matrix[i][j]); else - cwi = sprintf(buff, "% g", (double)matrix[i][j]); + cwi = snprintf(buff, sizeof(buff), "% g", (double)matrix[i][j]); cw[i] = GLM_MAX(cw[i], cwi); } } @@ -175,9 +175,9 @@ glm_mat3_print(mat3 matrix, for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { if (matrix[i][j] < CGLM_PRINT_MAX_TO_SHORT) - cwi = sprintf(buff, "% .*f", CGLM_PRINT_PRECISION, (double)matrix[i][j]); + cwi = snprintf(buff, sizeof(buff), "% .*f", CGLM_PRINT_PRECISION, (double)matrix[i][j]); else - cwi = sprintf(buff, "% g", (double)matrix[i][j]); + cwi = snprintf(buff, sizeof(buff), "% g", (double)matrix[i][j]); cw[i] = GLM_MAX(cw[i], cwi); } } @@ -217,9 +217,9 @@ glm_mat2_print(mat2 matrix, for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { if (matrix[i][j] < CGLM_PRINT_MAX_TO_SHORT) - cwi = sprintf(buff, "% .*f", CGLM_PRINT_PRECISION, (double)matrix[i][j]); + cwi = snprintf(buff, sizeof(buff), "% .*f", CGLM_PRINT_PRECISION, (double)matrix[i][j]); else - cwi = sprintf(buff, "% g", (double)matrix[i][j]); + cwi = snprintf(buff, sizeof(buff), "% g", (double)matrix[i][j]); cw[i] = GLM_MAX(cw[i], cwi); } } diff --git a/include/cglm/mat4.h b/include/cglm/mat4.h index 40a2b24..1c36c26 100644 --- a/include/cglm/mat4.h +++ b/include/cglm/mat4.h @@ -649,7 +649,9 @@ glm_mat4_det(mat4 mat) { CGLM_INLINE void glm_mat4_inv(mat4 mat, mat4 dest) { -#if defined( __SSE__ ) || defined( __SSE2__ ) +#if defined(__wasm__) && defined(__wasm_simd128__) + glm_mat4_inv_wasm(mat, dest); +#elif defined( __SSE__ ) || defined( __SSE2__ ) glm_mat4_inv_sse2(mat, dest); #elif defined(CGLM_NEON_FP) glm_mat4_inv_neon(mat, dest); diff --git a/include/cglm/noise.h b/include/cglm/noise.h new file mode 100644 index 0000000..bec12e9 --- /dev/null +++ b/include/cglm/noise.h @@ -0,0 +1,734 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + * + * Based on the work of Stefan Gustavson and Ashima Arts on "webgl-noise": + * https://github.com/stegu/webgl-noise + * Following Stefan Gustavson's paper "Simplex noise demystified": + * http://www.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf + * + * Implementation based on glm::perlin function: + * https://github.com/g-truc/glm/blob/master/glm/gtc/noise.inl + */ + +#ifndef cglm_noise_h +#define cglm_noise_h + +#include "vec4.h" +#include "vec4-ext.h" + +#include "vec3.h" +#include "vec3-ext.h" + +#include "vec2.h" +#include "vec2-ext.h" + +#define glm__noiseDetail_mod289(x) (x - floorf(x * (1.0f / 289.0f)) * 289.0f) + +/* glm__noiseDetail_permute(vec4 x, vec4 dest) */ +#define glm__noiseDetail_permute(x, dest) { \ + dest[0] = glm__noiseDetail_mod289((x[0] * 34.0f + 1.0f) * x[0]); \ + dest[1] = glm__noiseDetail_mod289((x[1] * 34.0f + 1.0f) * x[1]); \ + dest[2] = glm__noiseDetail_mod289((x[2] * 34.0f + 1.0f) * x[2]); \ + dest[3] = glm__noiseDetail_mod289((x[3] * 34.0f + 1.0f) * x[3]); \ +} + +/* glm__noiseDetail_fade_vec4(vec4 t, vec4 dest) */ +#define glm__noiseDetail_fade_vec4(t, dest) { \ + /* dest = (t * t * t) * (t * (t * 6.0f - 15.0f) + 10.0f) */ \ + vec4 temp; \ + glm_vec4_mul(t, t, temp); \ + glm_vec4_mul(temp, t, temp); \ + /* dest = (t * (t * 6.0f - 15.0f) + 10.0f) */ \ + glm_vec4_scale(t, 6.0f, dest); \ + glm_vec4_subs(dest, 15.0f, dest); \ + glm_vec4_mul(t, dest, dest); \ + glm_vec4_adds(dest, 10.0f, dest); \ + /* dest = temp * dest */ \ + glm_vec4_mul(temp, dest, dest); \ +} + +/* glm__noiseDetail_fade_vec3(vec3 t, vec3 dest) */ +#define glm__noiseDetail_fade_vec3(t, dest) { \ + /* dest = (t * t * t) * (t * (t * 6.0f - 15.0f) + 10.0f) */ \ + /* temp = t * t * t */ \ + vec3 temp; \ + glm_vec3_mul(t, t, temp); \ + glm_vec3_mul(temp, t, temp); \ + /* dest = (t * (t * 6.0f - 15.0f) + 10.0f) */ \ + glm_vec3_scale(t, 6.0f, dest); \ + glm_vec3_subs(dest, 15.0f, dest); \ + glm_vec3_mul(t, dest, dest); \ + glm_vec3_adds(dest, 10.0f, dest); \ + /* dest = temp * dest */ \ + glm_vec3_mul(temp, dest, dest); \ +} + +/* glm__noiseDetail_fade_vec2(vec2 t, vec2 dest) */ +#define glm__noiseDetail_fade_vec2(t, dest) { \ + /* dest = (t * t * t) * (t * (t * 6.0f - 15.0f) + 10.0f) */ \ + /* temp = t * t * t */ \ + vec2 temp; \ + glm_vec2_mul(t, t, temp); \ + glm_vec2_mul(temp, t, temp); \ + /* dest = (t * (t * 6.0f - 15.0f) + 10.0f) */ \ + glm_vec2_scale(t, 6.0f, dest); \ + glm_vec2_subs(dest, 15.0f, dest); \ + glm_vec2_mul(t, dest, dest); \ + glm_vec2_adds(dest, 10.0f, dest); \ + /* dest = temp * dest */ \ + glm_vec2_mul(temp, dest, dest); \ +} + +/* glm__noiseDetail_taylorInvSqrt(vec4 x, vec4 dest) */ +#define glm__noiseDetail_taylorInvSqrt(x, dest) { \ + /* dest = 1.79284291400159f - 0.85373472095314f * x */ \ + vec4 temp; \ + glm_vec4_scale(x, 0.85373472095314f, temp); /* temp = 0.853...f * x */ \ + glm_vec4_fill(dest, 1.79284291400159f); /* dest = 1.792...f */ \ + glm_vec4_sub(dest, temp, dest); /* dest = 1.79284291400159f - temp */ \ +} + +/* norm = taylorInvSqrt(vec4( + * dot(g00__, g00__), + * dot(g01__, g01__), + * dot(g10__, g10__), + * dot(g11__, g11__) + * )); +*/ + +/* glm__noiseDetail_gradNorm_vec4(vec4 g00__, vec4 g01__, vec4 g10__, vec4 g11__) */ +#define glm__noiseDetail_gradNorm_vec4(g00__, g01__, g10__, g11__) { \ + vec4 norm; \ + norm[0] = glm_vec4_dot(g00__, g00__); /* norm.x = dot(g00__, g00__) */ \ + norm[1] = glm_vec4_dot(g01__, g01__); /* norm.y = dot(g01__, g01__) */ \ + norm[2] = glm_vec4_dot(g10__, g10__); /* norm.z = dot(g10__, g10__) */ \ + norm[3] = glm_vec4_dot(g11__, g11__); /* norm.w = dot(g11__, g11__) */ \ + glm__noiseDetail_taylorInvSqrt(norm, norm); /* norm = taylorInvSqrt(norm) */ \ + \ + glm_vec4_scale(g00__, norm[0], g00__); /* g00__ *= norm.x */ \ + glm_vec4_scale(g01__, norm[1], g01__); /* g01__ *= norm.y */ \ + glm_vec4_scale(g10__, norm[2], g10__); /* g10__ *= norm.z */ \ + glm_vec4_scale(g11__, norm[3], g11__); /* g11__ *= norm.w */ \ +} + +/* glm__noiseDetail_gradNorm_vec3(vec3 g00_, vec3 g01_, vec3 g10_, vec3 g11_) */ +#define glm__noiseDetail_gradNorm_vec3(g00_, g01_, g10_, g11_) { \ + vec4 norm; \ + norm[0] = glm_vec3_dot(g00_, g00_); /* norm.x = dot(g00_, g00_) */ \ + norm[1] = glm_vec3_dot(g01_, g01_); /* norm.y = dot(g01_, g01_) */ \ + norm[2] = glm_vec3_dot(g10_, g10_); /* norm.z = dot(g10_, g10_) */ \ + norm[3] = glm_vec3_dot(g11_, g11_); /* norm.w = dot(g11_, g11_) */ \ + glm__noiseDetail_taylorInvSqrt(norm, norm); /* norm = taylorInvSqrt(norm) */ \ + \ + glm_vec3_scale(g00_, norm[0], g00_); /* g00_ *= norm.x */ \ + glm_vec3_scale(g01_, norm[1], g01_); /* g01_ *= norm.y */ \ + glm_vec3_scale(g10_, norm[2], g10_); /* g10_ *= norm.z */ \ + glm_vec3_scale(g11_, norm[3], g11_); /* g11_ *= norm.w */ \ +} + +/* glm__noiseDetail_gradNorm_vec2(vec2 g00, vec2 g01, vec2 g10, vec2 g11) */ +#define glm__noiseDetail_gradNorm_vec2(g00, g01, g10, g11) { \ + vec4 norm; \ + norm[0] = glm_vec2_dot(g00, g00); /* norm.x = dot(g00, g00) */ \ + norm[1] = glm_vec2_dot(g01, g01); /* norm.y = dot(g01, g01) */ \ + norm[2] = glm_vec2_dot(g10, g10); /* norm.z = dot(g10, g10) */ \ + norm[3] = glm_vec2_dot(g11, g11); /* norm.w = dot(g11, g11) */ \ + glm__noiseDetail_taylorInvSqrt(norm, norm); /* norm = taylorInvSqrt(norm) */ \ + \ + glm_vec2_scale(g00, norm[0], g00); /* g00 *= norm.x */ \ + glm_vec2_scale(g01, norm[1], g01); /* g01 *= norm.y */ \ + glm_vec2_scale(g10, norm[2], g10); /* g10 *= norm.z */ \ + glm_vec2_scale(g11, norm[3], g11); /* g11 *= norm.w */ \ +} + +/* glm__noiseDetail_i2gxyzw(vec4 ixy, vec4 gx, vec4 gy, vec4 gz, vec4 gw) */ +#define glm__noiseDetail_i2gxyzw(ixy, gx, gy, gz, gw) { \ + /* gx = ixy / 7.0 */ \ + glm_vec4_divs(ixy, 7.0f, gx); /* gx = ixy / 7.0 */ \ + \ + /* gy = fract(gx) / 7.0 */ \ + glm_vec4_floor(gx, gy); /* gy = floor(gx) */ \ + glm_vec4_divs(gy, 7.0f, gy); /* gy /= 7.0 */ \ + \ + /* gz = floor(gy) / 6.0 */ \ + glm_vec4_floor(gy, gz); /* gz = floor(gy) */ \ + glm_vec4_divs(gz, 6.0f, gz); /* gz /= 6.0 */ \ + \ + /* gx = fract(gx) - 0.5f */ \ + glm_vec4_fract(gx, gx); /* gx = fract(gx) */ \ + glm_vec4_subs(gx, 0.5f, gx); /* gx -= 0.5f */ \ + \ + /* gy = fract(gy) - 0.5f */ \ + glm_vec4_fract(gy, gy); /* gy = fract(gy) */ \ + glm_vec4_subs(gy, 0.5f, gy); /* gy -= 0.5f */ \ + \ + /* gz = fract(gz) - 0.5f */ \ + glm_vec4_fract(gz, gz); /* gz = fract(gz) */ \ + glm_vec4_subs(gz, 0.5f, gz); /* gz -= 0.5f */ \ + \ + /* abs(gx), abs(gy), abs(gz) */ \ + vec4 gxa, gya, gza; \ + glm_vec4_abs(gx, gxa); /* gxa = abs(gx) */ \ + glm_vec4_abs(gy, gya); /* gya = abs(gy) */ \ + glm_vec4_abs(gz, gza); /* gza = abs(gz) */ \ + \ + /* gw = 0.75 - abs(gx) - abs(gy) - abs(gz) */ \ + glm_vec4_fill(gw, 0.75f); /* gw = 0.75 */ \ + glm_vec4_sub(gw, gxa, gw); /* gw -= gxa */ \ + glm_vec4_sub(gw, gza, gw); /* gw -= gza */ \ + glm_vec4_sub(gw, gya, gw); /* gw -= gya */ \ + \ + /* sw = step(gw, 0.0); */ \ + vec4 sw; \ + glm_vec4_stepr(gw, 0.0f, sw); /* sw = step(gw, 0.0) */ \ + \ + /* gx -= sw * (step(vec4(0), gx) - T(0.5)); */ \ + vec4 temp = {0.0f}; /* temp = 0.0 */ \ + glm_vec4_step(temp, gx, temp); /* temp = step(temp, gx) */ \ + glm_vec4_subs(temp, 0.5f, temp); /* temp -= 0.5 */ \ + glm_vec4_mul(sw, temp, temp); /* temp *= sw */ \ + glm_vec4_sub(gx, temp, gx); /* gx -= temp */ \ + \ + /* gy -= sw * (step(vec4(0), gy) - T(0.5)); */ \ + glm_vec4_zero(temp); /* reset temp */ \ + glm_vec4_step(temp, gy, temp); /* temp = step(temp, gy) */ \ + glm_vec4_subs(temp, 0.5f, temp); /* temp -= 0.5 */ \ + glm_vec4_mul(sw, temp, temp); /* temp *= sw */ \ + glm_vec4_sub(gy, temp, gy); /* gy -= temp */ \ +} + +/* NOTE: This function is not *quite* analogous to glm__noiseDetail_i2gxyzw + * to try to match the output of glm::perlin. I think it might be a bug in + * in the original implementation, but for now I'm keeping it consistent. -MK + * + * Follow up: The original implementation (glm v 1.0.1) does: + * + * vec<4, T, Q> gx0 = ixy0 * T(1.0 / 7.0); + * + * as opposed to: + * + * vec<4, T, Q> gx0 = ixy0 / T(7); + * + * This ends up mapping to different simd instructions, at least on AMD. + * The delta is tiny but it gets amplified by the rest of the noise function. + * Hence we too need to do `glm_vec4_scale` as opposed to `glm_vec4_divs`, to + * match it. -MK + */ + +/* glm__noiseDetail_i2gxyz(vec4 i, vec4 gx, vec4 gy, vec4 gz) */ +#define glm__noiseDetail_i2gxyz(ixy, gx, gy, gz) { \ + /* gx = ixy / 7.0 */ \ + glm_vec4_scale(ixy, 1.0f / 7.0f, gx); /* gx = ixy * (1/7.0) */\ + \ + /* gy = fract(floor(gx0) / 7.0)) - 0.5; */ \ + glm_vec4_floor(gx, gy); /* gy = floor(gx) */ \ + glm_vec4_scale(gy, 1.0f / 7.0f, gy); /* gy *= 1 / 7.0 */ \ + glm_vec4_fract(gy, gy); /* gy = fract(gy) */ \ + glm_vec4_subs(gy, 0.5f, gy); /* gy -= 0.5f */ \ + \ + /* gx = fract(gx); */ \ + glm_vec4_fract(gx, gx); /* gx = fract(gx) */ \ + \ + /* abs(gx), abs(gy) */ \ + vec4 gxa, gya; \ + glm_vec4_abs(gx, gxa); /* gxa = abs(gx) */ \ + glm_vec4_abs(gy, gya); /* gya = abs(gy) */ \ + \ + /* gz = vec4(0.5) - abs(gx0) - abs(gy0); */ \ + glm_vec4_fill(gz, 0.5f); /* gz = 0.5 */ \ + glm_vec4_sub(gz, gxa, gz); /* gz -= gxa */ \ + glm_vec4_sub(gz, gya, gz); /* gz -= gya */ \ + \ + /* sz = step(gw, 0.0); */ \ + vec4 sz; \ + glm_vec4_stepr(gz, 0.0f, sz); /* sz = step(gz, 0.0) */ \ + \ + /* gx0 -= sz0 * (step(0.0, gx0) - T(0.5)); */ \ + vec4 temp = {0.0f}; /* temp = 0.0 */ \ + glm_vec4_step(temp, gx, temp); /* temp = step(temp, gx) */ \ + glm_vec4_subs(temp, 0.5f, temp); /* temp -= 0.5 */ \ + glm_vec4_mul(sz, temp, temp); /* temp *= sz */ \ + glm_vec4_sub(gx, temp, gx); /* gx -= temp */ \ + \ + /* gy0 -= sz0 * (step(0.0, gy0) - T(0.5)); */ \ + glm_vec4_zero(temp); /* reset temp */ \ + glm_vec4_step(temp, gy, temp); /* temp = step(temp, gy) */ \ + glm_vec4_subs(temp, 0.5f, temp); /* temp -= 0.5 */ \ + glm_vec4_mul(sz, temp, temp); /* temp *= sz */ \ + glm_vec4_sub(gy, temp, gy); /* gy -= temp */ \ +} + +/* glm__noiseDetail_i2gxy(vec4 i, vec4 gx, vec4 gy) */ +#define glm__noiseDetail_i2gxy(i, gx, gy) { \ + /* gx = 2.0 * fract(i / 41.0) - 1.0; */ \ + glm_vec4_divs(i, 41.0f, gx); /* gx = i / 41.0 */ \ + glm_vec4_fract(gx, gx); /* gx = fract(gx) */ \ + glm_vec4_scale(gx, 2.0f, gx); /* gx *= 2.0 */ \ + glm_vec4_subs(gx, 1.0f, gx); /* gx -= 1.0 */ \ + \ + /* gy = abs(gx) - 0.5; */ \ + glm_vec4_abs(gx, gy); /* gy = abs(gx) */ \ + glm_vec4_subs(gy, 0.5f, gy); /* gy -= 0.5 */ \ + \ + /* tx = floor(gx + 0.5); */ \ + vec4 tx; \ + glm_vec4_adds(gx, 0.5f, tx); /* tx = gx + 0.5 */ \ + glm_vec4_floor(tx, tx); /* tx = floor(tx) */ \ + \ + /* gx = gx - tx; */ \ + glm_vec4_sub(gx, tx, gx); /* gx -= tx */ \ +} + +/* ============================================================================ + * Classic perlin noise + * ============================================================================ + */ + +/*! + * @brief Classic perlin noise + * + * @param[in] point 4D vector + * @returns perlin noise value + */ +CGLM_INLINE +float +glm_perlin_vec4(vec4 point) { + /* Integer part of p for indexing */ + vec4 Pi0; + glm_vec4_floor(point, Pi0); /* Pi0 = floor(point); */ + + /* Integer part + 1 */ + vec4 Pi1; + glm_vec4_adds(Pi0, 1.0f, Pi1); /* Pi1 = Pi0 + 1.0f; */ + + glm_vec4_mods(Pi0, 289.0f, Pi0); /* Pi0 = mod(Pi0, 289.0f); */ + glm_vec4_mods(Pi1, 289.0f, Pi1); /* Pi1 = mod(Pi1, 289.0f); */ + + /* Fractional part of p for interpolation */ + vec4 Pf0; + glm_vec4_fract(point, Pf0); + + /* Fractional part - 1.0 */ + vec4 Pf1; + glm_vec4_subs(Pf0, 1.0f, Pf1); + + vec4 ix = {Pi0[0], Pi1[0], Pi0[0], Pi1[0]}; + vec4 iy = {Pi0[1], Pi0[1], Pi1[1], Pi1[1]}; + vec4 iz0 = {Pi0[2], Pi0[2], Pi0[2], Pi0[2]}; /* iz0 = vec4(Pi0.z); */ + vec4 iz1 = {Pi1[2], Pi1[2], Pi1[2], Pi1[2]}; /* iz1 = vec4(Pi1.z); */ + vec4 iw0 = {Pi0[3], Pi0[3], Pi0[3], Pi0[3]}; /* iw0 = vec4(Pi0.w); */ + vec4 iw1 = {Pi1[3], Pi1[3], Pi1[3], Pi1[3]}; /* iw1 = vec4(Pi1.w); */ + + /* ------------ */ + + /* ixy = permute(permute(ix) + iy) */ + vec4 ixy; + glm__noiseDetail_permute(ix, ixy); /* ixy = permute(ix) */ + glm_vec4_add(ixy, iy, ixy); /* ixy += iy; */ + glm__noiseDetail_permute(ixy, ixy); /* ixy = permute(ixy) */ + + /* ixy0 = permute(ixy + iz0) */ + vec4 ixy0; + glm_vec4_add(ixy, iz0, ixy0); /* ixy0 = ixy + iz0 */ + glm__noiseDetail_permute(ixy0, ixy0); /* ixy0 = permute(ixy0) */ + + /* ixy1 = permute(ixy + iz1) */ + vec4 ixy1; + glm_vec4_add(ixy, iz1, ixy1); /* ixy1 = ixy, iz1 */ + glm__noiseDetail_permute(ixy1, ixy1); /* ixy1 = permute(ixy1) */ + + /* ixy00 = permute(ixy0 + iw0) */ + vec4 ixy00; + glm_vec4_add(ixy0, iw0, ixy00); /* ixy00 = ixy0 + iw0 */ + glm__noiseDetail_permute(ixy00, ixy00); /* ixy00 = permute(ixy00) */ + + /* ixy01 = permute(ixy0 + iw1) */ + vec4 ixy01; + glm_vec4_add(ixy0, iw1, ixy01); /* ixy01 = ixy0 + iw1 */ + glm__noiseDetail_permute(ixy01, ixy01); /* ixy01 = permute(ixy01) */ + + /* ixy10 = permute(ixy1 + iw0) */ + vec4 ixy10; + glm_vec4_add(ixy1, iw0, ixy10); /* ixy10 = ixy1 + iw0 */ + glm__noiseDetail_permute(ixy10, ixy10); /* ixy10 = permute(ixy10) */ + + /* ixy11 = permute(ixy1 + iw1) */ + vec4 ixy11; + glm_vec4_add(ixy1, iw1, ixy11); /* ixy11 = ixy1 + iw1 */ + glm__noiseDetail_permute(ixy11, ixy11); /* ixy11 = permute(ixy11) */ + + /* ------------ */ + + vec4 gx00, gy00, gz00, gw00; + glm__noiseDetail_i2gxyzw(ixy00, gx00, gy00, gz00, gw00); + + vec4 gx01, gy01, gz01, gw01; + glm__noiseDetail_i2gxyzw(ixy01, gx01, gy01, gz01, gw01); + + vec4 gx10, gy10, gz10, gw10; + glm__noiseDetail_i2gxyzw(ixy10, gx10, gy10, gz10, gw10); + + vec4 gx11, gy11, gz11, gw11; + glm__noiseDetail_i2gxyzw(ixy11, gx11, gy11, gz11, gw11); + + /* ------------ */ + + vec4 g0000 = {gx00[0], gy00[0], gz00[0], gw00[0]}; /* g0000 = vec4(gx00.x, gy00.x, gz00.x, gw00.x); */ + vec4 g0100 = {gx00[2], gy00[2], gz00[2], gw00[2]}; /* g0100 = vec4(gx00.z, gy00.z, gz00.z, gw00.z); */ + vec4 g1000 = {gx00[1], gy00[1], gz00[1], gw00[1]}; /* g1000 = vec4(gx00.y, gy00.y, gz00.y, gw00.y); */ + vec4 g1100 = {gx00[3], gy00[3], gz00[3], gw00[3]}; /* g1100 = vec4(gx00.w, gy00.w, gz00.w, gw00.w); */ + + vec4 g0001 = {gx01[0], gy01[0], gz01[0], gw01[0]}; /* g0001 = vec4(gx01.x, gy01.x, gz01.x, gw01.x); */ + vec4 g0101 = {gx01[2], gy01[2], gz01[2], gw01[2]}; /* g0101 = vec4(gx01.z, gy01.z, gz01.z, gw01.z); */ + vec4 g1001 = {gx01[1], gy01[1], gz01[1], gw01[1]}; /* g1001 = vec4(gx01.y, gy01.y, gz01.y, gw01.y); */ + vec4 g1101 = {gx01[3], gy01[3], gz01[3], gw01[3]}; /* g1101 = vec4(gx01.w, gy01.w, gz01.w, gw01.w); */ + + vec4 g0010 = {gx10[0], gy10[0], gz10[0], gw10[0]}; /* g0010 = vec4(gx10.x, gy10.x, gz10.x, gw10.x); */ + vec4 g0110 = {gx10[2], gy10[2], gz10[2], gw10[2]}; /* g0110 = vec4(gx10.z, gy10.z, gz10.z, gw10.z); */ + vec4 g1010 = {gx10[1], gy10[1], gz10[1], gw10[1]}; /* g1010 = vec4(gx10.y, gy10.y, gz10.y, gw10.y); */ + vec4 g1110 = {gx10[3], gy10[3], gz10[3], gw10[3]}; /* g1110 = vec4(gx10.w, gy10.w, gz10.w, gw10.w); */ + + vec4 g0011 = {gx11[0], gy11[0], gz11[0], gw11[0]}; /* g0011 = vec4(gx11.x, gy11.x, gz11.x, gw11.x); */ + vec4 g0111 = {gx11[2], gy11[2], gz11[2], gw11[2]}; /* g0111 = vec4(gx11.z, gy11.z, gz11.z, gw11.z); */ + vec4 g1011 = {gx11[1], gy11[1], gz11[1], gw11[1]}; /* g1011 = vec4(gx11.y, gy11.y, gz11.y, gw11.y); */ + vec4 g1111 = {gx11[3], gy11[3], gz11[3], gw11[3]}; /* g1111 = vec4(gx11.w, gy11.w, gz11.w, gw11.w); */ + + glm__noiseDetail_gradNorm_vec4(g0000, g0100, g1000, g1100); + glm__noiseDetail_gradNorm_vec4(g0001, g0101, g1001, g1101); + glm__noiseDetail_gradNorm_vec4(g0010, g0110, g1010, g1110); + glm__noiseDetail_gradNorm_vec4(g0011, g0111, g1011, g1111); + + /* ------------ */ + + float n0000 = glm_vec4_dot(g0000, Pf0); /* n0000 = dot(g0000, Pf0) */ + + /* n1000 = dot(g1000, vec4(Pf1.x, Pf0.y, Pf0.z, Pf0.w)) */ + vec4 n1000d = {Pf1[0], Pf0[1], Pf0[2], Pf0[3]}; + float n1000 = glm_vec4_dot(g1000, n1000d); + + /* n0100 = dot(g0100, vec4(Pf0.x, Pf1.y, Pf0.z, Pf0.w)) */ + vec4 n0100d = {Pf0[0], Pf1[1], Pf0[2], Pf0[3]}; + float n0100 = glm_vec4_dot(g0100, n0100d); + + /* n1100 = dot(g1100, vec4(Pf1.x, Pf1.y, Pf0.z, Pf0.w)) */ + vec4 n1100d = {Pf1[0], Pf1[1], Pf0[2], Pf0[3]}; + float n1100 = glm_vec4_dot(g1100, n1100d); + + /* n0010 = dot(g0010, vec4(Pf0.x, Pf0.y, Pf1.z, Pf0.w)) */ + vec4 n0010d = {Pf0[0], Pf0[1], Pf1[2], Pf0[3]}; + float n0010 = glm_vec4_dot(g0010, n0010d); + + /* n1010 = dot(g1010, vec4(Pf1.x, Pf0.y, Pf1.z, Pf0.w)) */ + vec4 n1010d = {Pf1[0], Pf0[1], Pf1[2], Pf0[3]}; + float n1010 = glm_vec4_dot(g1010, n1010d); + + /* n0110 = dot(g0110, vec4(Pf0.x, Pf1.y, Pf1.z, Pf0.w)) */ + vec4 n0110d = {Pf0[0], Pf1[1], Pf1[2], Pf0[3]}; + float n0110 = glm_vec4_dot(g0110, n0110d); + + /* n1110 = dot(g1110, vec4(Pf1.x, Pf1.y, Pf1.z, Pf0.w)) */ + vec4 n1110d = {Pf1[0], Pf1[1], Pf1[2], Pf0[3]}; + float n1110 = glm_vec4_dot(g1110, n1110d); + + /* n0001 = dot(g0001, vec4(Pf0.x, Pf0.y, Pf0.z, Pf1.w)) */ + vec4 n0001d = {Pf0[0], Pf0[1], Pf0[2], Pf1[3]}; + float n0001 = glm_vec4_dot(g0001, n0001d); + + /* n1001 = dot(g1001, vec4(Pf1.x, Pf0.y, Pf0.z, Pf1.w)) */ + vec4 n1001d = {Pf1[0], Pf0[1], Pf0[2], Pf1[3]}; + float n1001 = glm_vec4_dot(g1001, n1001d); + + /* n0101 = dot(g0101, vec4(Pf0.x, Pf1.y, Pf0.z, Pf1.w)) */ + vec4 n0101d = {Pf0[0], Pf1[1], Pf0[2], Pf1[3]}; + float n0101 = glm_vec4_dot(g0101, n0101d); + + /* n1101 = dot(g1101, vec4(Pf1.x, Pf1.y, Pf0.z, Pf1.w)) */ + vec4 n1101d = {Pf1[0], Pf1[1], Pf0[2], Pf1[3]}; + float n1101 = glm_vec4_dot(g1101, n1101d); + + /* n0011 = dot(g0011, vec4(Pf0.x, Pf0.y, Pf1.z, Pf1.w)) */ + vec4 n0011d = {Pf0[0], Pf0[1], Pf1[2], Pf1[3]}; + float n0011 = glm_vec4_dot(g0011, n0011d); + + /* n1011 = dot(g1011, vec4(Pf1.x, Pf0.y, Pf1.z, Pf1.w)) */ + vec4 n1011d = {Pf1[0], Pf0[1], Pf1[2], Pf1[3]}; + float n1011 = glm_vec4_dot(g1011, n1011d); + + /* n0111 = dot(g0111, vec4(Pf0.x, Pf1.y, Pf1.z, Pf1.w)) */ + vec4 n0111d = {Pf0[0], Pf1[1], Pf1[2], Pf1[3]}; + float n0111 = glm_vec4_dot(g0111, n0111d); + + float n1111 = glm_vec4_dot(g1111, Pf1); /* n1111 = dot(g1111, Pf1) */ + + /* ------------ */ + + vec4 fade_xyzw; + glm__noiseDetail_fade_vec4(Pf0, fade_xyzw); /* fade_xyzw = fade(Pf0) */ + + /* n_0w = lerp(vec4(n0000, n1000, n0100, n1100), vec4(n0001, n1001, n0101, n1101), fade_xyzw.w) */ + vec4 n_0w1 = {n0000, n1000, n0100, n1100}; + vec4 n_0w2 = {n0001, n1001, n0101, n1101}; + vec4 n_0w; + glm_vec4_lerp(n_0w1, n_0w2, fade_xyzw[3], n_0w); + + /* n_1w = lerp(vec4(n0010, n1010, n0110, n1110), vec4(n0011, n1011, n0111, n1111), fade_xyzw.w) */ + vec4 n_1w1 = {n0010, n1010, n0110, n1110}; + vec4 n_1w2 = {n0011, n1011, n0111, n1111}; + vec4 n_1w; + glm_vec4_lerp(n_1w1, n_1w2, fade_xyzw[3], n_1w); + + /* n_zw = lerp(n_0w, n_1w, fade_xyzw.z) */ + vec4 n_zw; + glm_vec4_lerp(n_0w, n_1w, fade_xyzw[2], n_zw); + + /* n_yzw = lerp(vec2(n_zw.x, n_zw.y), vec2(n_zw.z, n_zw.w), fade_xyzw.y) */ + vec2 n_yzw; + vec2 n_yzw1 = {n_zw[0], n_zw[1]}; + vec2 n_yzw2 = {n_zw[2], n_zw[3]}; + glm_vec2_lerp(n_yzw1, n_yzw2, fade_xyzw[1], n_yzw); + + /* n_xyzw = lerp(n_yzw.x, n_yzw.y, fade_xyzw.x) */ + float n_xyzw = glm_lerp(n_yzw[0], n_yzw[1], fade_xyzw[0]); + + return n_xyzw * 2.2f; +} + + +/*! + * @brief Classic perlin noise + * + * @param[in] point 3D vector + * @returns perlin noise value + */ +CGLM_INLINE +float +glm_perlin_vec3(vec3 point) { + /* Integer part of p for indexing */ + vec3 Pi0; + glm_vec3_floor(point, Pi0); /* Pi0 = floor(point); */ + + /* Integer part + 1 */ + vec3 Pi1; + glm_vec3_adds(Pi0, 1.0f, Pi1); /* Pi1 = Pi0 + 1.0f; */ + + glm_vec3_mods(Pi0, 289.0f, Pi0); /* Pi0 = mod(Pi0, 289.0f); */ + glm_vec3_mods(Pi1, 289.0f, Pi1); /* Pi1 = mod(Pi1, 289.0f); */ + + /* Fractional part of p for interpolation */ + vec3 Pf0; + glm_vec3_fract(point, Pf0); + + /* Fractional part - 1.0 */ + vec3 Pf1; + glm_vec3_subs(Pf0, 1.0f, Pf1); + + vec4 ix = {Pi0[0], Pi1[0], Pi0[0], Pi1[0]}; + vec4 iy = {Pi0[1], Pi0[1], Pi1[1], Pi1[1]}; + vec4 iz0 = {Pi0[2], Pi0[2], Pi0[2], Pi0[2]}; /* iz0 = vec4(Pi0.z); */ + vec4 iz1 = {Pi1[2], Pi1[2], Pi1[2], Pi1[2]}; /* iz1 = vec4(Pi1.z); */ + + /* ------------ */ + + /* ixy = permute(permute(ix) + iy) */ + vec4 ixy; + glm__noiseDetail_permute(ix, ixy); /* ixy = permute(ix) */ + glm_vec4_add(ixy, iy, ixy); /* ixy += iy; */ + glm__noiseDetail_permute(ixy, ixy); /* ixy = permute(ixy) */ + + /* ixy0 = permute(ixy + iz0) */ + vec4 ixy0; + glm_vec4_add(ixy, iz0, ixy0); /* ixy0 = ixy + iz0 */ + glm__noiseDetail_permute(ixy0, ixy0); /* ixy0 = permute(ixy0) */ + + /* ixy1 = permute(ixy + iz1) */ + vec4 ixy1; + glm_vec4_add(ixy, iz1, ixy1); /* ixy1 = ixy, iz1 */ + glm__noiseDetail_permute(ixy1, ixy1); /* ixy1 = permute(ixy1) */ + + /* ------------ */ + + vec4 gx0, gy0, gz0; + glm__noiseDetail_i2gxyz(ixy0, gx0, gy0, gz0); + + vec4 gx1, gy1, gz1; + glm__noiseDetail_i2gxyz(ixy1, gx1, gy1, gz1); + + /* ------------ */ + + vec3 g000 = {gx0[0], gy0[0], gz0[0]}; /* g000 = vec3(gx0.x, gy0.x, gz0.x); */ + vec3 g100 = {gx0[1], gy0[1], gz0[1]}; /* g100 = vec3(gx0.y, gy0.y, gz0.y); */ + vec3 g010 = {gx0[2], gy0[2], gz0[2]}; /* g010 = vec3(gx0.z, gy0.z, gz0.z); */ + vec3 g110 = {gx0[3], gy0[3], gz0[3]}; /* g110 = vec3(gx0.w, gy0.w, gz0.w); */ + + vec3 g001 = {gx1[0], gy1[0], gz1[0]}; /* g001 = vec3(gx1.x, gy1.x, gz1.x); */ + vec3 g101 = {gx1[1], gy1[1], gz1[1]}; /* g101 = vec3(gx1.y, gy1.y, gz1.y); */ + vec3 g011 = {gx1[2], gy1[2], gz1[2]}; /* g011 = vec3(gx1.z, gy1.z, gz1.z); */ + vec3 g111 = {gx1[3], gy1[3], gz1[3]}; /* g111 = vec3(gx1.w, gy1.w, gz1.w); */ + + glm__noiseDetail_gradNorm_vec3(g000, g010, g100, g110); + glm__noiseDetail_gradNorm_vec3(g001, g011, g101, g111); + + /* ------------ */ + + float n000 = glm_vec3_dot(g000, Pf0); /* n000 = dot(g000, Pf0) */ + + /* n100 = dot(g100, vec3(Pf1.x, Pf0.y, Pf0.z)) */ + vec3 n100d = {Pf1[0], Pf0[1], Pf0[2]}; + float n100 = glm_vec3_dot(g100, n100d); + + /* n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z)) */ + vec3 n010d = {Pf0[0], Pf1[1], Pf0[2]}; + float n010 = glm_vec3_dot(g010, n010d); + + /* n110 = dot(g110, vec3(Pf1.x, Pf1.y, Pf0.z)) */ + vec3 n110d = {Pf1[0], Pf1[1], Pf0[2]}; + float n110 = glm_vec3_dot(g110, n110d); + + /* n001 = dot(g001, vec3(Pf0.x, Pf0.y, Pf1.z)) */ + vec3 n001d = {Pf0[0], Pf0[1], Pf1[2]}; + float n001 = glm_vec3_dot(g001, n001d); + + /* n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z)) */ + vec3 n101d = {Pf1[0], Pf0[1], Pf1[2]}; + float n101 = glm_vec3_dot(g101, n101d); + + /* n011 = dot(g011, vec3(Pf0.x, Pf1.y, Pf1.z)) */ + vec3 n011d = {Pf0[0], Pf1[1], Pf1[2]}; + float n011 = glm_vec3_dot(g011, n011d); + + float n111 = glm_vec3_dot(g111, Pf1); /* n111 = dot(g111, Pf1) */ + + /* ------------ */ + + vec3 fade_xyz; + glm__noiseDetail_fade_vec3(Pf0, fade_xyz); /* fade_xyz = fade(Pf0) */ + + /* n_z = lerp(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z); */ + vec4 n_z; + vec4 n_z1 = {n000, n100, n010, n110}; + vec4 n_z2 = {n001, n101, n011, n111}; + glm_vec4_lerp(n_z1, n_z2, fade_xyz[2], n_z); + + /* vec2 n_yz = lerp(vec2(n_z.x, n_z.y), vec2(n_z.z, n_z.w), fade_xyz.y); */ + vec2 n_yz; + vec2 n_yz1 = {n_z[0], n_z[1]}; + vec2 n_yz2 = {n_z[2], n_z[3]}; + glm_vec2_lerp(n_yz1, n_yz2, fade_xyz[1], n_yz); + + /* n_xyz = lerp(n_yz.x, n_yz.y, fade_xyz.x); */ + float n_xyz = glm_lerp(n_yz[0], n_yz[1], fade_xyz[0]); + + return n_xyz * 2.2f; +} + +/*! + * @brief Classic perlin noise + * + * @param[in] point 2D vector + * @returns perlin noise value + */ +CGLM_INLINE +float +glm_perlin_vec2(vec2 point) { + + /* Integer part of p for indexing */ + /* Pi = floor(vec4(point.x, point.y, point.x, point.y)) + vec4(0.0, 0.0, 1.0, 1.0); */ + vec4 Pi = {point[0], point[1], point[0], point[1]}; /* Pi = vec4(point.x, point.y, point.x, point.y) */ + glm_vec4_floor(Pi, Pi); /* Pi = floor(Pi) */ + Pi[2] += 1.0f; /* Pi.z += 1.0 */ + Pi[3] += 1.0f; /* Pi.w += 1.0 */ + + /* Fractional part of p for interpolation */ + /* vec<4, T, Q> Pf = glm::fract(vec<4, T, Q>(Position.x, Position.y, Position.x, Position.y)) - vec<4, T, Q>(0.0, 0.0, 1.0, 1.0); */ + vec4 Pf = {point[0], point[1], point[0], point[1]}; /* Pf = vec4(point.x, point.y, point.x, point.y) */ + glm_vec4_fract(Pf, Pf); /* Pf = fract(Pf) */ + Pf[2] -= 1.0f; /* Pf.z -= 1.0 */ + Pf[3] -= 1.0f; /* Pf.w -= 1.0 */ + + /* Mod to avoid truncation effects in permutation */ + glm_vec4_mods(Pi, 289.0f, Pi); /* Pi = mod(Pi, 289.0f); */ + + vec4 ix = {Pi[0], Pi[2], Pi[0], Pi[2]}; /* ix = vec4(Pi.x, Pi.z, Pi.x, Pi.z) */ + vec4 iy = {Pi[1], Pi[1], Pi[3], Pi[3]}; /* iy = vec4(Pi.y, Pi.y, Pi.w, Pi.w) */ + vec4 fx = {Pf[0], Pf[2], Pf[0], Pf[2]}; /* fx = vec4(Pf.x, Pf.z, Pf.x, Pf.z) */ + vec4 fy = {Pf[1], Pf[1], Pf[3], Pf[3]}; /* fy = vec4(Pf.y, Pf.y, Pf.w, Pf.w) */ + + /* ------------ */ + + /* i = permute(permute(ix) + iy); */ + vec4 i; + glm__noiseDetail_permute(ix, i); /* i = permute(ix) */ + glm_vec4_add(i, iy, i); /* i += iy; */ + glm__noiseDetail_permute(i, i); /* i = permute(i) */ + + /* ------------ */ + + vec4 gx, gy; + glm__noiseDetail_i2gxy(i, gx, gy); + + /* ------------ */ + + vec2 g00 = {gx[0], gy[0]}; /* g00 = vec2(gx.x, gy.x) */ + vec2 g10 = {gx[1], gy[1]}; /* g10 = vec2(gx.y, gy.y) */ + vec2 g01 = {gx[2], gy[2]}; /* g01 = vec2(gx.z, gy.z) */ + vec2 g11 = {gx[3], gy[3]}; /* g11 = vec2(gx.w, gy.w) */ + + glm__noiseDetail_gradNorm_vec2(g00, g01, g10, g11); + + /* ------------ */ + + /* n00 = dot(g00, vec2(fx.x, fy.x)) */ + vec2 n00d = {fx[0], fy[0]}; /* n00d = vec2(fx.x, fy.x) */ + float n00 = glm_vec2_dot(g00, n00d); /* n00 = dot(g00, n00d) */ + + /* n10 = dot(g10, vec2(fx.y, fy.y)) */ + vec2 n10d = {fx[1], fy[1]}; /* n10d = vec2(fx.y, fy.y) */ + float n10 = glm_vec2_dot(g10, n10d); /* n10 = dot(g10, n10d) */ + + /* n01 = dot(g01, vec2(fx.z, fy.z)) */ + vec2 n01d = {fx[2], fy[2]}; /* n01d = vec2(fx.z, fy.z) */ + float n01 = glm_vec2_dot(g01, n01d); /* n01 = dot(g01, n01d) */ + + /* n11 = dot(g11, vec2(fx.w, fy.w)) */ + vec2 n11d = {fx[3], fy[3]}; /* n11d = vec2(fx.w, fy.w) */ + float n11 = glm_vec2_dot(g11, n11d); /* n11 = dot(g11, n11d) */ + + /* ------------ */ + + /* fade_xyz = fade(vec2(Pf.x, Pf.y)) */ + vec2 fade_xy; + vec2 temp2 = {Pf[0], Pf[1]}; /* temp = vec2(Pf.x, Pf.y) */ + glm__noiseDetail_fade_vec2(temp2, fade_xy); /* fade_xy = fade(temp) */ + + /* n_x = lerp(vec2(n00, n01), vec2(n10, n11), fade_xy.x); */ + vec2 n_x; + vec2 n_x1 = {n00, n01}; /* n_x1 = vec2(n00, n01) */ + vec2 n_x2 = {n10, n11}; /* n_x2 = vec2(n10, n11) */ + glm_vec2_lerp(n_x1, n_x2, fade_xy[0], n_x); /* n_x = lerp(n_x1, n_x2, fade_xy.x) */ + + /* T n_xy = mix(n_x.x, n_x.y, fade_xy.y); */ + /* n_xy = lerp(n_x.x, n_x.y, fade_xy.y); */ + float n_xy = glm_lerp(n_x[0], n_x[1], fade_xy[1]); + + return n_xy * 2.3f; +} + +/* Undefine all helper macros */ + +#undef glm__noiseDetail_mod289 +#undef glm__noiseDetail_permute +#undef glm__noiseDetail_fade_vec4 +#undef glm__noiseDetail_fade_vec3 +#undef glm__noiseDetail_fade_vec2 +#undef glm__noiseDetail_taylorInvSqrt +#undef glm__noiseDetail_gradNorm_vec4 +#undef glm__noiseDetail_gradNorm_vec3 +#undef glm__noiseDetail_gradNorm_vec2 +#undef glm__noiseDetail_i2gxyzw +#undef glm__noiseDetail_i2gxyz +#undef glm__noiseDetail_i2gxy + +#endif /* cglm_noise_h */ diff --git a/include/cglm/quat.h b/include/cglm/quat.h index 18892d3..cf1f325 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -39,6 +39,7 @@ CGLM_INLINE void glm_quat_lerp(versor from, versor to, float t, versor dest); CGLM_INLINE void glm_quat_lerpc(versor from, versor to, float t, versor dest); CGLM_INLINE void glm_quat_slerp(versor q, versor r, float t, versor dest); + CGLM_INLINE void glm_quat_slerp_longest(versor q, versor r, float t, versor dest); CGLM_INLINE void glm_quat_nlerp(versor q, versor r, float t, versor dest); CGLM_INLINE void glm_quat_look(vec3 eye, versor ori, mat4 dest); CGLM_INLINE void glm_quat_for(vec3 dir, vec3 fwd, vec3 up, versor dest); @@ -122,7 +123,7 @@ glm_quat_identity_array(versor * __restrict q, size_t count) { } /*! - * @brief inits quaterion with raw values + * @brief inits quaternion with raw values * * @param[out] q quaternion * @param[in] x x @@ -742,6 +743,52 @@ glm_quat_slerp(versor from, versor to, float t, versor dest) { glm_vec4_scale(q1, 1.0f / sinTheta, dest); } +/*! + * @brief interpolates between two quaternions + * using spherical linear interpolation (SLERP) and always takes the long path + * + * @param[in] from from + * @param[in] to to + * @param[in] t amount + * @param[out] dest result quaternion + */ +CGLM_INLINE +void +glm_quat_slerp_longest(versor from, versor to, float t, versor dest) { + CGLM_ALIGN(16) vec4 q1, q2; + float cosTheta, sinTheta, angle; + + cosTheta = glm_quat_dot(from, to); + glm_quat_copy(from, q1); + + if (fabsf(cosTheta) >= 1.0f) { + glm_quat_copy(q1, dest); + return; + } + + /* longest path */ + if (!(cosTheta < 0.0f)) { + glm_vec4_negate(q1); + cosTheta = -cosTheta; + } + + sinTheta = sqrtf(1.0f - cosTheta * cosTheta); + + /* LERP to avoid zero division */ + if (fabsf(sinTheta) < 0.001f) { + glm_quat_lerp(from, to, t, dest); + return; + } + + /* SLERP */ + angle = acosf(cosTheta); + glm_vec4_scale(q1, sinf((1.0f - t) * angle), q1); + glm_vec4_scale(to, sinf(t * angle), q2); + + glm_vec4_add(q1, q2, q1); + glm_vec4_scale(q1, 1.0f / sinTheta, dest); +} + /*! * @brief creates view matrix using quaternion as camera orientation * diff --git a/include/cglm/struct.h b/include/cglm/struct.h index 1426589..31ca4e2 100644 --- a/include/cglm/struct.h +++ b/include/cglm/struct.h @@ -31,6 +31,7 @@ extern "C" { #include "struct/affine.h" #include "struct/frustum.h" #include "struct/plane.h" +#include "struct/noise.h" #include "struct/box.h" #include "struct/color.h" #include "struct/io.h" diff --git a/include/cglm/struct/aabb2d.h b/include/cglm/struct/aabb2d.h index e66eb34..9077069 100644 --- a/include/cglm/struct/aabb2d.h +++ b/include/cglm/struct/aabb2d.h @@ -62,7 +62,7 @@ glms_aabb2d_(merge)(vec2s aabb1[2], vec2s aabb2[2], vec2s dest[2]) { /*! * @brief crops a bounding box with another one. * - * this could be useful for gettng a bbox which fits with view frustum and + * this could be useful for getting a bbox which fits with view frustum and * object bounding boxes. In this case you crop view frustum box with objects * box * @@ -86,7 +86,7 @@ glms_aabb2d_(crop)(vec2s aabb[2], vec2s cropAabb[2], vec2s dest[2]) { /*! * @brief crops a bounding box with another one. * - * this could be useful for gettng a bbox which fits with view frustum and + * this could be useful for getting a bbox which fits with view frustum and * object bounding boxes. In this case you crop view frustum box with objects * box * @@ -137,8 +137,27 @@ glms_aabb2d_(isvalid)(vec2s aabb[2]) { */ CGLM_INLINE float -glms_aabb2d_(size)(vec2s aabb[2]) { - return glm_vec2_distance(aabb[0].raw, aabb[1].raw); +glms_aabb2d_(diag)(vec2s aabb[2]) { + vec2 rawAabb[2]; + glms_vec2_(unpack)(rawAabb, aabb, 2); + return glm_aabb2d_diag(rawAabb); +} + + +/*! + * @brief size of aabb + * + * @param[in] aabb bounding aabb + * @param[out] dest size + */ +CGLM_INLINE +vec2s +glms_aabb2d_(sizev)(vec2s aabb[2]) { + vec2s size; + vec2 rawAabb[2]; + glms_vec2_(unpack)(rawAabb, aabb, 2); + glm_aabb2d_sizev(rawAabb, size.raw); + return size; } /*! @@ -232,4 +251,3 @@ glms_aabb2d_(contains)(vec2s aabb[2], vec2s other[2]) { } #endif /* cglms_aabb2ds_h */ - diff --git a/include/cglm/struct/box.h b/include/cglm/struct/box.h index 96ae03b..ac32328 100644 --- a/include/cglm/struct/box.h +++ b/include/cglm/struct/box.h @@ -62,7 +62,7 @@ glms_aabb_(merge)(vec3s box1[2], vec3s box2[2], vec3s dest[2]) { /*! * @brief crops a bounding box with another one. * - * this could be useful for gettng a bbox which fits with view frustum and + * this could be useful for getting a bbox which fits with view frustum and * object bounding boxes. In this case you crop view frustum box with objects * box * @@ -86,7 +86,7 @@ glms_aabb_(crop)(vec3s box[2], vec3s cropBox[2], vec3s dest[2]) { /*! * @brief crops a bounding box with another one. * - * this could be useful for gettng a bbox which fits with view frustum and + * this could be useful for getting a bbox which fits with view frustum and * object bounding boxes. In this case you crop view frustum box with objects * box * diff --git a/include/cglm/struct/ivec2.h b/include/cglm/struct/ivec2.h index ad1c416..d53c9f6 100644 --- a/include/cglm/struct/ivec2.h +++ b/include/cglm/struct/ivec2.h @@ -238,7 +238,7 @@ glms_ivec2_(subs)(ivec2s v, int s) { /*! * @brief multiply vector [a] with vector [b] and store result in [dest] * - * @param[in] a frist vector + * @param[in] a first vector * @param[in] b second vector * @returns destination */ diff --git a/include/cglm/struct/ivec3.h b/include/cglm/struct/ivec3.h index 3d24a1b..c2c5f3b 100644 --- a/include/cglm/struct/ivec3.h +++ b/include/cglm/struct/ivec3.h @@ -163,7 +163,7 @@ glms_ivec3_(dot)(ivec3s a, ivec3s b) { * @brief norm * norm (magnitude) of vec * * we can use this func instead of calling norm * norm, because it would call - * sqrtf fuction twice but with this func we can avoid func call, maybe this is + * sqrtf function twice but with this func we can avoid func call, maybe this is * not good name for this func * * @param[in] v vector @@ -253,7 +253,7 @@ glms_ivec3_(subs)(ivec3s v, int s) { /*! * @brief multiply vector [a] with vector [b] and store result in [dest] * - * @param[in] a frist vector + * @param[in] a first vector * @param[in] b second vector * @returns destination */ diff --git a/include/cglm/struct/ivec4.h b/include/cglm/struct/ivec4.h index e8f29a1..103e887 100644 --- a/include/cglm/struct/ivec4.h +++ b/include/cglm/struct/ivec4.h @@ -201,7 +201,7 @@ glms_ivec4_(subs)(ivec4s v, int s) { /*! * @brief multiply vector [a] with vector [b] and store result in [dest] * - * @param[in] a frist vector + * @param[in] a first vector * @param[in] b second vector * @returns destination */ diff --git a/include/cglm/struct/noise.h b/include/cglm/struct/noise.h new file mode 100644 index 0000000..3fd7d2e --- /dev/null +++ b/include/cglm/struct/noise.h @@ -0,0 +1,57 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglms_noises_h +#define cglms_noises_h + +#include "../common.h" +#include "../types-struct.h" +#include "../noise.h" +#include "vec4.h" + +/* + Functions: + CGLM_INLINE float glms_perlin_vec4(vec4s point); + */ + +/*! + * @brief Classic perlin noise + * + * @param[in] point 4D vector + * @returns perlin noise value + */ +CGLM_INLINE +float +glms_perlin_vec4(vec4s point) { + return glm_perlin_vec4(point.raw); +} + +/*! + * @brief Classic perlin noise + * + * @param[in] point 3D vector + * @returns perlin noise value + */ +CGLM_INLINE +float +glms_perlin_vec3(vec3s point) { + return glm_perlin_vec3(point.raw); +} + +/*! + * @brief Classic perlin noise + * + * @param[in] point 2D vector + * @returns perlin noise value + */ +CGLM_INLINE +float +glms_perlin_vec2(vec2s point) { + return glm_perlin_vec2(point.raw); +} + +#endif /* cglms_noises_h */ diff --git a/include/cglm/struct/quat.h b/include/cglm/struct/quat.h index 859b664..d6789e4 100644 --- a/include/cglm/struct/quat.h +++ b/include/cglm/struct/quat.h @@ -37,6 +37,7 @@ CGLM_INLINE versors glms_quat_lerpc(versors from, versors to, float t) CGLM_INLINE versors glms_quat_nlerp(versors from, versors to, float t) CGLM_INLINE versors glms_quat_slerp(versors from, versors to, float t) + CGLM_INLINE versors glms_quat_slerp_longest(versors from, versors to, float t) CGLM_INLINE mat4s. glms_quat_look(vec3s eye, versors ori) CGLM_INLINE versors glms_quat_for(vec3s dir, vec3s fwd, vec3s up) CGLM_INLINE versors glms_quat_forp(vec3s from, vec3s to, vec3s fwd, vec3s up) @@ -104,7 +105,7 @@ glms_quat_(identity_array)(versors * __restrict q, size_t count) { } /*! - * @brief inits quaterion with raw values + * @brief inits quaternion with raw values * * @param[in] x x * @param[in] y y @@ -457,6 +458,23 @@ glms_quat_(slerp)(versors from, versors to, float t) { return dest; } +/*! + * @brief interpolates between two quaternions + * using spherical linear interpolation (SLERP) and always takes the longest path + * + * @param[in] from from + * @param[in] to to + * @param[in] t amount + * @returns result quaternion + */ +CGLM_INLINE +versors +glms_quat_(slerp_longest)(versors from, versors to, float t) { + versors dest; + glm_quat_slerp_longest(from.raw, to.raw, t, dest.raw); + return dest; +} + /*! * @brief creates view matrix using quaternion as camera orientation * diff --git a/include/cglm/struct/vec2-ext.h b/include/cglm/struct/vec2-ext.h index f467aeb..246132f 100644 --- a/include/cglm/struct/vec2-ext.h +++ b/include/cglm/struct/vec2-ext.h @@ -23,6 +23,12 @@ CGLM_INLINE bool glms_vec2_isinf(vec2s v) CGLM_INLINE bool glms_vec2_isvalid(vec2s v) CGLM_INLINE vec2s glms_vec2_sign(vec2s v) + CGLM_INLINE vec2s glms_vec2_abs(vec2s v) + CGLM_INLINE vec2s glms_vec2_fract(vec2s v) + CGLM_INLINE vec2s glms_vec2_floor(vec2s v) + CGLM_INLINE vec2s glms_vec2_mods(vec2s v, float s) + CGLM_INLINE vec2s glms_vec2_steps(float edge, vec2s v) + CGLM_INLINE vec2s glms_vec2_stepr(vec2s edge, float v) CGLM_INLINE vec2s glms_vec2_sqrt(vec2s v) */ @@ -133,7 +139,7 @@ glms_vec2_min(vec2s v) { } /*! - * @brief check if all items are NaN (not a number) + * @brief check if one of items is NaN (not a number) * you should only use this in DEBUG mode or very critical asserts * * @param[in] v vector @@ -145,7 +151,7 @@ glms_vec2_(isnan)(vec2s v) { } /*! - * @brief check if all items are INFINITY + * @brief check if one of items is INFINITY * you should only use this in DEBUG mode or very critical asserts * * @param[in] v vector @@ -184,6 +190,95 @@ glms_vec2_(sign)(vec2s v) { return r; } +/*! + * @brief fractional part of each vector item + * + * @param v vector + * @returns abs vector + */ +CGLM_INLINE +vec2s +glms_vec2_(abs)(vec2s v) { + vec2s r; + glm_vec2_abs(v.raw, r.raw); + return r; +} + +/*! + * @brief fractional part of each vector item + * + * @param[in] v vector + * @returns destination vector + */ +CGLM_INLINE +vec2s +glms_vec2_(fract)(vec2s v) { + vec2s r; + glm_vec2_fract(v.raw, r.raw); + return r; +} + +/*! + * @brief floor of each vector item + * + * @param[in] v vector + * @returns destination vector + */ +CGLM_INLINE +vec2s +glms_vec2_(floor)(vec2s v) { + vec2s r; + glm_vec2_floor(v.raw, r.raw); + return r; +} + +/*! + * @brief mod of each vector item by scalar + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec2s +glms_vec2_(mods)(vec2s v, float s) { + vec2s r; + glm_vec2_mods(v.raw, s, r.raw); + return r; +} + +/*! + * @brief threshold each vector item with scalar + * condition is: (x[i] < edge) ? 0.0 : 1.0 + * + * @param[in] edge threshold + * @param[in] x vector to test against threshold + * @returns destination + */ +CGLM_INLINE +vec2s +glms_vec2_(steps)(float edge, vec2s x) { + vec2s r; + glm_vec2_steps(edge, x.raw, r.raw); + return r; +} + +/*! + * @brief threshold a value with *vector* as the threshold + * condition is: (x < edge[i]) ? 0.0 : 1.0 + * + * @param[in] edge threshold vector + * @param[in] x value to test against threshold + * @returns destination + */ +CGLM_INLINE +vec2s +glms_vec2_(stepr)(vec2s edge, float x) { + vec2s r; + glm_vec2_stepr(edge.raw, x, r.raw); + return r; +} + /*! * @brief square root of each vector item * diff --git a/include/cglm/struct/vec2.h b/include/cglm/struct/vec2.h index e1190e2..40ed659 100644 --- a/include/cglm/struct/vec2.h +++ b/include/cglm/struct/vec2.h @@ -53,6 +53,7 @@ CGLM_INLINE vec2s glms_vec2_minv(vec2s a, vec2s b) CGLM_INLINE vec2s glms_vec2_clamp(vec2s v, float minVal, float maxVal) CGLM_INLINE vec2s glms_vec2_lerp(vec2s from, vec2s to, float t) + CGLM_INLINE vec2s glms_vec2_step(vec2s edge, vec2s x) CGLM_INLINE vec2s glms_vec2_make(float * restrict src) CGLM_INLINE vec2s glms_vec2_reflect(vec2s v, vec2s n) CGLM_INLINE bool glms_vec2_refract(vec2s v, vec2s n, float eta, vec2s *dest) @@ -679,6 +680,21 @@ glms_vec2_(lerp)(vec2s from, vec2s to, float t) { return r; } +/*! + * @brief threshold function + * + * @param[in] edge threshold + * @param[in] x value to test against threshold + * @returns destination + */ +CGLM_INLINE +vec2s +glms_vec2_(step)(vec2s edge, vec2s x) { + vec2s r; + glm_vec2_step(edge.raw, x.raw, r.raw); + return r; +} + /*! * @brief Create two dimensional vector from pointer * diff --git a/include/cglm/struct/vec3-ext.h b/include/cglm/struct/vec3-ext.h index 31fb6c2..6cd8ca0 100644 --- a/include/cglm/struct/vec3-ext.h +++ b/include/cglm/struct/vec3-ext.h @@ -26,6 +26,10 @@ CGLM_INLINE vec3s glms_vec3_sign(vec3s v); CGLM_INLINE vec3s glms_vec3_abs(vec3s v); CGLM_INLINE vec3s glms_vec3_fract(vec3s v); + CGLM_INLINE vec3s glms_vec3_floor(vec3s v); + CGLM_INLINE vec3s glms_vec3_mods(vec3s v, float s); + CGLM_INLINE vec3s glms_vec3_steps(float edge, vec3s v); + CGLM_INLINE vec3s glms_vec3_stepr(vec3s edge, float v); CGLM_INLINE float glms_vec3_hadd(vec3s v); CGLM_INLINE vec3s glms_vec3_sqrt(vec3s v); */ @@ -151,7 +155,7 @@ glms_vec3_(min)(vec3s v) { } /*! - * @brief check if all items are NaN (not a number) + * @brief check if one of items is NaN (not a number) * you should only use this in DEBUG mode or very critical asserts * * @param[in] v vector @@ -163,7 +167,7 @@ glms_vec3_(isnan)(vec3s v) { } /*! - * @brief check if all items are INFINITY + * @brief check if one of items is INFINITY * you should only use this in DEBUG mode or very critical asserts * * @param[in] v vector @@ -230,6 +234,67 @@ glms_vec3_(fract)(vec3s v) { return r; } +/*! + * @brief floor of each vector item + * + * @param[in] v vector + * @return dest destination vector + */ +CGLM_INLINE +vec3s +glms_vec3_(floor)(vec3s v) { + vec3s r; + glm_vec3_floor(v.raw, r.raw); + return r; +} + +/*! + * @brief mod of each vector item by scalar + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec3s +glms_vec3_(mods)(vec3s v, float s) { + vec3s r; + glm_vec3_mods(v.raw, s, r.raw); + return r; +} + +/*! + * @brief threshold each vector item with scalar + * condition is: (x[i] < edge) ? 0.0 : 1.0 + * + * @param[in] edge threshold + * @param[in] x vector to test against threshold + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3_(steps)(float edge, vec3s x) { + vec3s r; + glm_vec3_steps(edge, x.raw, r.raw); + return r; +} + +/*! + * @brief threshold a value with *vector* as the threshold + * condition is: (x < edge[i]) ? 0.0 : 1.0 + * + * @param[in] edge threshold vector + * @param[in] x value to test against threshold + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3_(stepr)(vec3s edge, float x) { + vec3s r; + glm_vec3_stepr(edge.raw, x, r.raw); + return r; +} + /*! * @brief vector reduction by summation * @warning could overflow diff --git a/include/cglm/struct/vec3.h b/include/cglm/struct/vec3.h index 536af03..a1d901e 100644 --- a/include/cglm/struct/vec3.h +++ b/include/cglm/struct/vec3.h @@ -68,7 +68,6 @@ CGLM_INLINE vec3s glms_vec3_lerpc(vec3s from, vec3s to, float t); CGLM_INLINE vec3s glms_vec3_mix(vec3s from, vec3s to, float t); CGLM_INLINE vec3s glms_vec3_mixc(vec3s from, vec3s to, float t); - CGLM_INLINE vec3s glms_vec3_step_uni(float edge, vec3s x); CGLM_INLINE vec3s glms_vec3_step(vec3s edge, vec3s x); CGLM_INLINE vec3s glms_vec3_smoothstep_uni(float edge0, float edge1, vec3s x); CGLM_INLINE vec3s glms_vec3_smoothstep(vec3s edge0, vec3s edge1, vec3s x); @@ -84,6 +83,9 @@ CGLM_INLINE vec3s glms_cross(vec3s a, vec3s b); CGLM_INLINE float glms_dot(vec3s a, vec3s b); CGLM_INLINE vec3s glms_normalize(vec3s v); + + Deprecated: + glms_vec3_step_uni --> use glms_vec3_steps */ #ifndef cglms_vec3s_h @@ -95,6 +97,9 @@ #include "../vec3.h" #include "vec3-ext.h" +/* DEPRECATED! */ +#define glms_vec3_step_uni(edge, x) glms_vec3_steps(edge, x) + #define GLMS_VEC3_ONE_INIT {GLM_VEC3_ONE_INIT} #define GLMS_VEC3_ZERO_INIT {GLM_VEC3_ZERO_INIT} @@ -910,21 +915,6 @@ glms_vec3_(mixc)(vec3s from, vec3s to, float t) { return r; } -/*! - * @brief threshold function (unidimensional) - * - * @param[in] edge threshold - * @param[in] x value to test against threshold - * @returns 0.0 if x < edge, else 1.0 - */ -CGLM_INLINE -vec3s -glms_vec3_(step_uni)(float edge, vec3s x) { - vec3s r; - glm_vec3_step_uni(edge, x.raw, r.raw); - return r; -} - /*! * @brief threshold function * diff --git a/include/cglm/struct/vec4-ext.h b/include/cglm/struct/vec4-ext.h index 6f48d93..f57348e 100644 --- a/include/cglm/struct/vec4-ext.h +++ b/include/cglm/struct/vec4-ext.h @@ -26,6 +26,10 @@ CGLM_INLINE vec4s glms_vec4_sign(vec4s v); CGLM_INLINE vec4s glms_vec4_abs(vec4s v); CGLM_INLINE vec4s glms_vec4_fract(vec4s v); + CGLM_INLINE float glms_vec4_floor(vec4s v); + CGLM_INLINE float glms_vec4_mods(vec4s v, float s); + CGLM_INLINE float glms_vec4_steps(float edge, vec4s v); + CGLM_INLINE void glms_vec4_stepr(vec4s edge, float v); CGLM_INLINE float glms_vec4_hadd(vec4s v); CGLM_INLINE vec4s glms_vec4_sqrt(vec4s v); */ @@ -230,6 +234,67 @@ glms_vec4_(fract)(vec4s v) { return r; } +/*! + * @brief floor of each vector item + * + * @param[in] v vector + * @returns dest destination vector + */ +CGLM_INLINE +vec4s +glms_vec4_(floor)(vec4s v) { + vec4s r; + glm_vec4_floor(v.raw, r.raw); + return r; +} + +/*! + * @brief mod of each vector item by scalar + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec4s +glms_vec4_(mods)(vec4s v, float s) { + vec4s r; + glm_vec4_mods(v.raw, s, r.raw); + return r; +} + +/*! + * @brief threshold each vector item with scalar + * condition is: (x[i] < edge) ? 0.0 : 1.0 + * + * @param[in] edge threshold + * @param[in] x vector to test against threshold + * @returns destination + */ +CGLM_INLINE +vec4s +glms_vec4_(steps)(float edge, vec4s x) { + vec4s r; + glm_vec4_steps(edge, x.raw, r.raw); + return r; +} + +/*! + * @brief threshold a value with *vector* as the threshold + * condition is: (x < edge[i]) ? 0.0 : 1.0 + * + * @param[in] edge threshold vector + * @param[in] x value to test against threshold + * @returns destination + */ +CGLM_INLINE +vec4s +glms_vec4_(stepr)(vec4s edge, float x) { + vec4s r; + glm_vec4_stepr(edge.raw, x, r.raw); + return r; +} + /*! * @brief vector reduction by summation * @warning could overflow diff --git a/include/cglm/struct/vec4.h b/include/cglm/struct/vec4.h index 8b2ef00..a64c1a3 100644 --- a/include/cglm/struct/vec4.h +++ b/include/cglm/struct/vec4.h @@ -58,7 +58,6 @@ CGLM_INLINE vec4s glms_vec4_lerpc(vec4s from, vec4s to, float t); CGLM_INLINE vec4s glms_vec4_mix(vec4s from, vec4s to, float t); CGLM_INLINE vec4s glms_vec4_mixc(vec4s from, vec4s to, float t); - CGLM_INLINE vec4s glms_vec4_step_uni(float edge, vec4s x); CGLM_INLINE vec4s glms_vec4_step(vec4s edge, vec4s x); CGLM_INLINE vec4s glms_vec4_smoothstep_uni(float edge0, float edge1, vec4s x); CGLM_INLINE vec4s glms_vec4_smoothstep(vec4s edge0, vec4s edge1, vec4s x); @@ -69,6 +68,9 @@ CGLM_INLINE vec4s glms_vec4_make(float * restrict src); CGLM_INLINE vec4s glms_vec4_reflect(vec4s v, vec4s n); CGLM_INLINE bool glms_vec4_refract(vec4s v, vec4s n, float eta, vec4s *dest) + + Deprecated: + glms_vec4_step_uni --> use glms_vec4_steps */ #ifndef cglms_vec4s_h @@ -80,6 +82,9 @@ #include "../vec4.h" #include "vec4-ext.h" +/* DEPRECATED! */ +#define glms_vec4_step_uni(edge, x) glms_vec4_steps(edge, x) + #define GLMS_VEC4_ONE_INIT {GLM_VEC4_ONE_INIT} #define GLMS_VEC4_BLACK_INIT {GLM_VEC4_BLACK_INIT} #define GLMS_VEC4_ZERO_INIT {GLM_VEC4_ZERO_INIT} @@ -786,21 +791,6 @@ glms_vec4_(mixc)(vec4s from, vec4s to, float t) { return r; } -/*! - * @brief threshold function (unidimensional) - * - * @param[in] edge threshold - * @param[in] x value to test against threshold - * @returns 0.0 if x < edge, else 1.0 - */ -CGLM_INLINE -vec4s -glms_vec4_(step_uni)(float edge, vec4s x) { - vec4s r; - glm_vec4_step_uni(edge, x.raw, r.raw); - return r; -} - /*! * @brief threshold function * diff --git a/include/cglm/types-struct.h b/include/cglm/types-struct.h index 0a3ad0f..d93152e 100644 --- a/include/cglm/types-struct.h +++ b/include/cglm/types-struct.h @@ -24,6 +24,12 @@ /* The user has defined CGLM_NO_ANONYMOUS_STRUCT. This used to be the * only #define governing the use of anonymous structs, so for backward * compatibility, we still honor that choice and disable them. */ +# define CGLM_USE_ANONYMOUS_STRUCT 0 + /* Disable anonymous structs if strict ANSI mode is enabled for C89 or C99 */ +# elif defined(__STRICT_ANSI__) && \ + (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 201112L)) + /* __STRICT_ANSI__ is defined and we're in C89 + * or C99 mode (C11 or later not detected) */ # define CGLM_USE_ANONYMOUS_STRUCT 0 # elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \ (defined(__cplusplus) && __cplusplus >= 201103L) diff --git a/include/cglm/vec2-ext.h b/include/cglm/vec2-ext.h index 1015a39..6186f07 100644 --- a/include/cglm/vec2-ext.h +++ b/include/cglm/vec2-ext.h @@ -20,6 +20,11 @@ CGLM_INLINE bool glm_vec2_isvalid(vec2 v); CGLM_INLINE void glm_vec2_sign(vec2 v, vec2 dest); CGLM_INLINE void glm_vec2_abs(vec2 v, vec2 dest); + CGLM_INLINE void glm_vec2_fract(vec2 v, vec2 dest); + CGLM_INLINE void glm_vec2_floor(vec2 v, vec2 dest); + CGLM_INLINE float glm_vec2_mods(vec2 v, float s, vec2 dest); + CGLM_INLINE float glm_vec2_steps(float edge, vec2 v, vec2 dest); + CGLM_INLINE void glm_vec2_stepr(vec2 edge, float v, vec2 dest); CGLM_INLINE void glm_vec2_sqrt(vec2 v, vec2 dest); CGLM_INLINE void glm_vec2_complex_mul(vec2 a, vec2 b, vec2 dest) CGLM_INLINE void glm_vec2_complex_div(vec2 a, vec2 b, vec2 dest) @@ -128,7 +133,7 @@ glm_vec2_min(vec2 v) { } /*! - * @brief check if all items are NaN (not a number) + * @brief check if one of items is NaN (not a number) * you should only use this in DEBUG mode or very critical asserts * * @param[in] v vector @@ -136,11 +141,15 @@ glm_vec2_min(vec2 v) { CGLM_INLINE bool glm_vec2_isnan(vec2 v) { +#ifndef CGLM_FAST_MATH return isnan(v[0]) || isnan(v[1]); +#else + return false; +#endif } /*! - * @brief check if all items are INFINITY + * @brief check if one of items is INFINITY * you should only use this in DEBUG mode or very critical asserts * * @param[in] v vector @@ -148,7 +157,11 @@ glm_vec2_isnan(vec2 v) { CGLM_INLINE bool glm_vec2_isinf(vec2 v) { +#ifndef CGLM_FAST_MATH return isinf(v[0]) || isinf(v[1]); +#else + return false; +#endif } /*! @@ -190,6 +203,46 @@ glm_vec2_abs(vec2 v, vec2 dest) { dest[1] = fabsf(v[1]); } +/*! + * @brief fractional part of each vector item + * + * @param[in] v vector + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec2_fract(vec2 v, vec2 dest) { + dest[0] = fminf(v[0] - floorf(v[0]), 0.999999940395355224609375f); + dest[1] = fminf(v[1] - floorf(v[1]), 0.999999940395355224609375f); +} + +/*! + * @brief floor of each vector item + * + * @param[in] v vector + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec2_floor(vec2 v, vec2 dest) { + dest[0] = floorf(v[0]); + dest[1] = floorf(v[1]); +} + +/*! + * @brief mod of each vector item, result is written to dest (dest = v % s) + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec2_mods(vec2 v, float s, vec2 dest) { + dest[0] = fmodf(v[0], s); + dest[1] = fmodf(v[1], s); +} + /*! * @brief square root of each vector item * @@ -220,6 +273,36 @@ glm_vec2_complex_mul(vec2 a, vec2 b, vec2 dest) { dest[1] = ti; } +/*! + * @brief threshold each vector item with scalar + * condition is: (x[i] < edge) ? 0.0 : 1.0 + * + * @param[in] edge threshold + * @param[in] x vector to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec2_steps(float edge, vec2 x, vec2 dest) { + dest[0] = glm_step(edge, x[0]); + dest[1] = glm_step(edge, x[1]); +} + +/*! + * @brief threshold a value with *vector* as the threshold + * condition is: (x < edge[i]) ? 0.0 : 1.0 + * + * @param[in] edge threshold vector + * @param[in] x value to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec2_stepr(vec2 edge, float x, vec2 dest) { + dest[0] = glm_step(edge[0], x); + dest[1] = glm_step(edge[1], x); +} + /*! * @brief treat vectors as complex numbers and divide them as such. * diff --git a/include/cglm/vec2.h b/include/cglm/vec2.h index aaac759..655fb4b 100644 --- a/include/cglm/vec2.h +++ b/include/cglm/vec2.h @@ -53,7 +53,9 @@ CGLM_INLINE void glm_vec2_maxv(vec2 v1, vec2 v2, vec2 dest) CGLM_INLINE void glm_vec2_minv(vec2 v1, vec2 v2, vec2 dest) CGLM_INLINE void glm_vec2_clamp(vec2 v, float minVal, float maxVal) + CGLM_INLINE void glm_vec2_swizzle(vec2 v, int mask, vec2 dest) CGLM_INLINE void glm_vec2_lerp(vec2 from, vec2 to, float t, vec2 dest) + CGLM_INLINE void glm_vec2_step(vec2 edge, vec2 x, vec2 dest) CGLM_INLINE void glm_vec2_make(float * restrict src, vec2 dest) CGLM_INLINE void glm_vec2_reflect(vec2 v, vec2 n, vec2 dest) CGLM_INLINE void glm_vec2_refract(vec2 v, vec2 n, float eta, vec2 dest) @@ -679,6 +681,24 @@ glm_vec2_clamp(vec2 v, float minval, float maxval) { v[1] = glm_clamp(v[1], minval, maxval); } +/*! + * @brief swizzle vector components + * + * @param[in] v source + * @param[in] mask mask + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec2_swizzle(vec2 v, int mask, vec2 dest) { + vec2 t; + + t[0] = v[(mask & (3 << 0))]; + t[1] = v[(mask & (3 << 2)) >> 2]; + + glm_vec2_copy(t, dest); +} + /*! * @brief linear interpolation between two vector * @@ -701,6 +721,20 @@ glm_vec2_lerp(vec2 from, vec2 to, float t, vec2 dest) { glm_vec2_add(from, v, dest); } +/*! + * @brief threshold function + * + * @param[in] edge threshold + * @param[in] x value to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec2_step(vec2 edge, vec2 x, vec2 dest) { + dest[0] = glm_step(edge[0], x[0]); + dest[1] = glm_step(edge[1], x[1]); +} + /*! * @brief Create two dimensional vector from pointer * @@ -749,7 +783,7 @@ glm_vec2_refract(vec2 v, vec2 n, float eta, vec2 dest) { ndi = glm_vec2_dot(n, v); eni = eta * ndi; - k = 1.0f + eta * eta - eni * eni; + k = 1.0f - eta * eta + eni * eni; if (k < 0.0f) { glm_vec2_zero(dest); diff --git a/include/cglm/vec3-ext.h b/include/cglm/vec3-ext.h index bea5583..4413cc2 100644 --- a/include/cglm/vec3-ext.h +++ b/include/cglm/vec3-ext.h @@ -26,6 +26,10 @@ CGLM_INLINE void glm_vec3_sign(vec3 v, vec3 dest); CGLM_INLINE void glm_vec3_abs(vec3 v, vec3 dest); CGLM_INLINE void glm_vec3_fract(vec3 v, vec3 dest); + CGLM_INLINE void glm_vec3_floor(vec3 v, vec3 dest); + CGLM_INLINE float glm_vec3_mods(vec3 v, float s, vec3 dest); + CGLM_INLINE float glm_vec3_steps(float edge, vec3 v, vec3 dest); + CGLM_INLINE void glm_vec3_stepr(vec3 edge, float v, vec3 dest); CGLM_INLINE float glm_vec3_hadd(vec3 v); CGLM_INLINE void glm_vec3_sqrt(vec3 v, vec3 dest); */ @@ -164,7 +168,7 @@ glm_vec3_min(vec3 v) { } /*! - * @brief check if all items are NaN (not a number) + * @brief check if one of items is NaN (not a number) * you should only use this in DEBUG mode or very critical asserts * * @param[in] v vector @@ -172,11 +176,15 @@ glm_vec3_min(vec3 v) { CGLM_INLINE bool glm_vec3_isnan(vec3 v) { +#ifndef CGLM_FAST_MATH return isnan(v[0]) || isnan(v[1]) || isnan(v[2]); +#else + return false; +#endif } /*! - * @brief check if all items are INFINITY + * @brief check if one of items is INFINITY * you should only use this in DEBUG mode or very critical asserts * * @param[in] v vector @@ -184,7 +192,11 @@ glm_vec3_isnan(vec3 v) { CGLM_INLINE bool glm_vec3_isinf(vec3 v) { +#ifndef CGLM_FAST_MATH return isinf(v[0]) || isinf(v[1]) || isinf(v[2]); +#else + return false; +#endif } /*! @@ -242,6 +254,67 @@ glm_vec3_fract(vec3 v, vec3 dest) { dest[2] = fminf(v[2] - floorf(v[2]), 0.999999940395355224609375f); } +/*! + * @brief floor of each vector item + * + * @param[in] v vector + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec3_floor(vec3 v, vec3 dest) { + dest[0] = floorf(v[0]); + dest[1] = floorf(v[1]); + dest[2] = floorf(v[2]); +} + +/*! + * @brief mod of each vector item, result is written to dest (dest = v % s) + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec3_mods(vec3 v, float s, vec3 dest) { + dest[0] = fmodf(v[0], s); + dest[1] = fmodf(v[1], s); + dest[2] = fmodf(v[2], s); +} + +/*! + * @brief threshold each vector item with scalar + * condition is: (x[i] < edge) ? 0.0 : 1.0 + * + * @param[in] edge threshold + * @param[in] x vector to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_steps(float edge, vec3 x, vec3 dest) { + dest[0] = glm_step(edge, x[0]); + dest[1] = glm_step(edge, x[1]); + dest[2] = glm_step(edge, x[2]); +} + +/*! + * @brief threshold a value with *vector* as the threshold + * condition is: (x < edge[i]) ? 0.0 : 1.0 + * + * @param[in] edge threshold vector + * @param[in] x value to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_stepr(vec3 edge, float x, vec3 dest) { + dest[0] = glm_step(edge[0], x); + dest[1] = glm_step(edge[1], x); + dest[2] = glm_step(edge[2], x); +} + /*! * @brief vector reduction by summation * @warning could overflow diff --git a/include/cglm/vec3.h b/include/cglm/vec3.h index be4029b..1350818 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -72,7 +72,6 @@ CGLM_INLINE void glm_vec3_lerpc(vec3 from, vec3 to, float t, vec3 dest); CGLM_INLINE void glm_vec3_mix(vec3 from, vec3 to, float t, vec3 dest); CGLM_INLINE void glm_vec3_mixc(vec3 from, vec3 to, float t, vec3 dest); - CGLM_INLINE void glm_vec3_step_uni(float edge, vec3 x, vec3 dest); CGLM_INLINE void glm_vec3_step(vec3 edge, vec3 x, vec3 dest); CGLM_INLINE void glm_vec3_smoothstep_uni(float edge0, float edge1, vec3 x, vec3 dest); CGLM_INLINE void glm_vec3_smoothstep(vec3 edge0, vec3 edge1, vec3 x, vec3 dest); @@ -97,6 +96,7 @@ glm_vec3_inv glm_vec3_inv_to glm_vec3_mulv + glm_vec3_step_uni --> use glm_vec3_steps */ #ifndef cglm_vec3_h @@ -114,6 +114,7 @@ #define glm_vec3_inv(v) glm_vec3_negate(v) #define glm_vec3_inv_to(v, dest) glm_vec3_negate_to(v, dest) #define glm_vec3_mulv(a, b, d) glm_vec3_mul(a, b, d) +#define glm_vec3_step_uni(edge, x, dest) glm_vec3_steps(edge, x, dest) #define GLM_VEC3_ONE_INIT {1.0f, 1.0f, 1.0f} #define GLM_VEC3_ZERO_INIT {0.0f, 0.0f, 0.0f} @@ -1012,21 +1013,6 @@ glm_vec3_mixc(vec3 from, vec3 to, float t, vec3 dest) { glm_vec3_lerpc(from, to, t, dest); } -/*! - * @brief threshold function (unidimensional) - * - * @param[in] edge threshold - * @param[in] x value to test against threshold - * @param[out] dest destination - */ -CGLM_INLINE -void -glm_vec3_step_uni(float edge, vec3 x, vec3 dest) { - dest[0] = glm_step(edge, x[0]); - dest[1] = glm_step(edge, x[1]); - dest[2] = glm_step(edge, x[2]); -} - /*! * @brief threshold function * @@ -1263,7 +1249,7 @@ glm_vec3_refract(vec3 v, vec3 n, float eta, vec3 dest) { ndi = glm_vec3_dot(n, v); eni = eta * ndi; - k = 1.0f + eta * eta - eni * eni; + k = 1.0f - eta * eta + eni * eni; if (k < 0.0f) { glm_vec3_zero(dest); diff --git a/include/cglm/vec4-ext.h b/include/cglm/vec4-ext.h index b3850a0..193a5e9 100644 --- a/include/cglm/vec4-ext.h +++ b/include/cglm/vec4-ext.h @@ -26,6 +26,10 @@ CGLM_INLINE void glm_vec4_sign(vec4 v, vec4 dest); CGLM_INLINE void glm_vec4_abs(vec4 v, vec4 dest); CGLM_INLINE void glm_vec4_fract(vec4 v, vec4 dest); + CGLM_INLINE void glm_vec4_floor(vec4 v, vec4 dest); + CGLM_INLINE float glm_vec4_mods(vec4 v, float s, vec4 dest); + CGLM_INLINE float glm_vec4_steps(float edge, vec4 v, vec4 dest); + CGLM_INLINE void glm_vec4_stepr(vec4 edge, float v, vec4 dest); CGLM_INLINE float glm_vec4_hadd(vec4 v); CGLM_INLINE void glm_vec4_sqrt(vec4 v, vec4 dest); */ @@ -186,7 +190,11 @@ glm_vec4_min(vec4 v) { CGLM_INLINE bool glm_vec4_isnan(vec4 v) { +#ifndef CGLM_FAST_MATH return isnan(v[0]) || isnan(v[1]) || isnan(v[2]) || isnan(v[3]); +#else + return false; +#endif } /*! @@ -198,7 +206,11 @@ glm_vec4_isnan(vec4 v) { CGLM_INLINE bool glm_vec4_isinf(vec4 v) { +#ifndef CGLM_FAST_MATH return isinf(v[0]) || isinf(v[1]) || isinf(v[2]) || isinf(v[3]); +#else + return false; +#endif } /*! @@ -280,6 +292,71 @@ glm_vec4_fract(vec4 v, vec4 dest) { dest[3] = fminf(v[3] - floorf(v[3]), 0.999999940395355224609375f); } +/*! + * @brief floor of each vector item + * + * @param[in] v vector + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec4_floor(vec4 v, vec4 dest) { + dest[0] = floorf(v[0]); + dest[1] = floorf(v[1]); + dest[2] = floorf(v[2]); + dest[3] = floorf(v[3]); +} + +/*! + * @brief mod of each vector item, result is written to dest (dest = v % s) + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec4_mods(vec4 v, float s, vec4 dest) { + dest[0] = fmodf(v[0], s); + dest[1] = fmodf(v[1], s); + dest[2] = fmodf(v[2], s); + dest[3] = fmodf(v[3], s); +} + +/*! + * @brief threshold each vector item with scalar + * condition is: (x[i] < edge) ? 0.0 : 1.0 + * + * @param[in] edge threshold + * @param[in] x vector to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_steps(float edge, vec4 x, vec4 dest) { + dest[0] = glm_step(edge, x[0]); + dest[1] = glm_step(edge, x[1]); + dest[2] = glm_step(edge, x[2]); + dest[3] = glm_step(edge, x[3]); +} + +/*! + * @brief threshold a value with *vector* as the threshold + * condition is: (x < edge[i]) ? 0.0 : 1.0 + * + * @param[in] edge threshold vector + * @param[in] x value to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_stepr(vec4 edge, float x, vec4 dest) { + dest[0] = glm_step(edge[0], x); + dest[1] = glm_step(edge[1], x); + dest[2] = glm_step(edge[2], x); + dest[3] = glm_step(edge[3], x); +} + /*! * @brief vector reduction by summation * @warning could overflow diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index 2d18d8c..b36af7f 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -57,7 +57,6 @@ CGLM_INLINE void glm_vec4_clamp(vec4 v, float minVal, float maxVal); CGLM_INLINE void glm_vec4_lerp(vec4 from, vec4 to, float t, vec4 dest); CGLM_INLINE void glm_vec4_lerpc(vec4 from, vec4 to, float t, vec4 dest); - CGLM_INLINE void glm_vec4_step_uni(float edge, vec4 x, vec4 dest); CGLM_INLINE void glm_vec4_step(vec4 edge, vec4 x, vec4 dest); CGLM_INLINE void glm_vec4_smoothstep_uni(float edge0, float edge1, vec4 x, vec4 dest); CGLM_INLINE void glm_vec4_smoothstep(vec4 edge0, vec4 edge1, vec4 x, vec4 dest); @@ -75,6 +74,7 @@ glm_vec4_inv glm_vec4_inv_to glm_vec4_mulv + glm_vec4_step_uni --> use glm_vec4_steps */ #ifndef cglm_vec4_h @@ -92,6 +92,7 @@ #define glm_vec4_inv(v) glm_vec4_negate(v) #define glm_vec4_inv_to(v, dest) glm_vec4_negate_to(v, dest) #define glm_vec4_mulv(a, b, d) glm_vec4_mul(a, b, d) +#define glm_vec4_step_uni(edge, x, dest) glm_vec4_steps(edge, x, dest) #define GLM_VEC4_ONE_INIT {1.0f, 1.0f, 1.0f, 1.0f} #define GLM_VEC4_BLACK_INIT {0.0f, 0.0f, 0.0f, 1.0f} @@ -529,6 +530,8 @@ glm_vec4_divs(vec4 v, float s, vec4 dest) { glmm_store(dest, wasm_f32x4_div(glmm_load(v), wasm_f32x4_splat(s))); #elif defined( __SSE__ ) || defined( __SSE2__ ) glmm_store(dest, _mm_div_ps(glmm_load(v), glmm_set1(s))); +#elif defined(CGLM_NEON_FP) + vst1q_f32(dest, vdivq_f32(vld1q_f32(v), vdupq_n_f32(s))); #else glm_vec4_scale(v, 1.0f / s, dest); #endif @@ -1148,22 +1151,6 @@ glm_vec4_mixc(vec4 from, vec4 to, float t, vec4 dest) { glm_vec4_lerpc(from, to, t, dest); } -/*! - * @brief threshold function (unidimensional) - * - * @param[in] edge threshold - * @param[in] x value to test against threshold - * @param[out] dest destination - */ -CGLM_INLINE -void -glm_vec4_step_uni(float edge, vec4 x, vec4 dest) { - dest[0] = glm_step(edge, x[0]); - dest[1] = glm_step(edge, x[1]); - dest[2] = glm_step(edge, x[2]); - dest[3] = glm_step(edge, x[3]); -} - /*! * @brief threshold function * @@ -1350,7 +1337,7 @@ glm_vec4_refract(vec4 v, vec4 n, float eta, vec4 dest) { ndi = glm_vec4_dot(n, v); eni = eta * ndi; - k = 1.0f + eta * eta - eni * eni; + k = 1.0f - eta * eta + eni * eni; if (k < 0.0f) { glm_vec4_zero(dest); diff --git a/meson.build b/meson.build index 3afdc4f..485a1b0 100644 --- a/meson.build +++ b/meson.build @@ -56,8 +56,10 @@ cglm_src = files( 'src/mat4x2.c', 'src/mat4x3.c', 'src/plane.c', + 'src/noise.c', 'src/frustum.c', 'src/box.c', + 'src/aabb2d.c', 'src/project.c', 'src/sphere.c', 'src/ease.c', diff --git a/src/euler.c b/src/euler.c index 2b0fe0f..8749ba5 100644 --- a/src/euler.c +++ b/src/euler.c @@ -97,4 +97,3 @@ void glmc_euler_zyx_quat(vec3 angles, versor dest) { glm_euler_zyx_quat(angles, dest); } - diff --git a/src/ivec2.c b/src/ivec2.c index 0e39b5b..2fd0993 100644 --- a/src/ivec2.c +++ b/src/ivec2.c @@ -247,4 +247,3 @@ void glmc_ivec2_abs(ivec2 v, ivec2 dest) { glm_ivec2_abs(v, dest); } - diff --git a/src/ivec3.c b/src/ivec3.c index 7644c99..4a2ea2f 100644 --- a/src/ivec3.c +++ b/src/ivec3.c @@ -253,4 +253,3 @@ void glmc_ivec3_abs(ivec3 v, ivec3 dest) { glm_ivec3_abs(v, dest); } - diff --git a/src/ivec4.c b/src/ivec4.c index 4f57a3b..1e976a6 100644 --- a/src/ivec4.c +++ b/src/ivec4.c @@ -199,4 +199,3 @@ void glmc_ivec4_abs(ivec4 v, ivec4 dest) { glm_ivec4_abs(v, dest); } - diff --git a/src/noise.c b/src/noise.c new file mode 100644 index 0000000..f464202 --- /dev/null +++ b/src/noise.c @@ -0,0 +1,27 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#include "../include/cglm/cglm.h" +#include "../include/cglm/call.h" + +CGLM_EXPORT +float +glmc_perlin_vec4(vec4 p) { + return glm_perlin_vec4(p); +} + +CGLM_EXPORT +float +glmc_perlin_vec3(vec3 p) { + return glm_perlin_vec3(p); +} + +CGLM_EXPORT +float +glmc_perlin_vec2(vec2 p) { + return glm_perlin_vec2(p); +} \ No newline at end of file diff --git a/src/quat.c b/src/quat.c index 56cda30..3f41286 100644 --- a/src/quat.c +++ b/src/quat.c @@ -188,6 +188,12 @@ glmc_quat_slerp(versor from, versor to, float t, versor dest) { glm_quat_slerp(from, to, t, dest); } +CGLM_EXPORT +void +glmc_quat_slerp_longest(versor from, versor to, float t, versor dest) { + glm_quat_slerp_longest(from, to, t, dest); +} + CGLM_EXPORT void glmc_quat_look(vec3 eye, versor ori, mat4 dest) { diff --git a/src/vec2.c b/src/vec2.c index b124f86..479c41e 100644 --- a/src/vec2.c +++ b/src/vec2.c @@ -273,6 +273,48 @@ glmc_vec2_abs(vec2 v, vec2 dest) { glm_vec2_abs(v, dest); } +CGLM_EXPORT +void +glmc_vec2_fract(vec2 v, vec2 dest) { + glm_vec2_fract(v, dest); +} + +CGLM_EXPORT +void +glmc_vec2_floor(vec2 v, vec2 dest) { + glm_vec2_floor(v, dest); +} + +CGLM_EXPORT +void +glmc_vec2_mods(vec2 v, float s, vec2 dest) { + glm_vec2_mods(v, s, dest); +} + +CGLM_EXPORT +void +glmc_vec2_step(vec2 edge, vec2 v, vec2 dest) { + glm_vec2_step(edge, v, dest); +} + +CGLM_EXPORT +void +glmc_vec2_steps(float edge, vec2 v, vec2 dest) { + glm_vec2_steps(edge, v, dest); +} + +CGLM_EXPORT +void +glmc_vec2_stepr(vec2 edge, float v, vec2 dest) { + glm_vec2_stepr(edge, v, dest); +} + +CGLM_EXPORT +void +glmc_vec2_swizzle(vec2 v, int mask, vec2 dest) { + glm_vec2_swizzle(v, mask, dest); +} + CGLM_EXPORT void glmc_vec2_lerp(vec2 from, vec2 to, float t, vec2 dest) { diff --git a/src/vec3.c b/src/vec3.c index c1316dc..a8c1083 100644 --- a/src/vec3.c +++ b/src/vec3.c @@ -308,12 +308,6 @@ glmc_vec3_lerpc(vec3 from, vec3 to, float t, vec3 dest) { glm_vec3_lerpc(from, to, t, dest); } -CGLM_EXPORT -void -glmc_vec3_step_uni(float edge, vec3 x, vec3 dest) { - glm_vec3_step_uni(edge, x, dest); -} - CGLM_EXPORT void glmc_vec3_step(vec3 edge, vec3 x, vec3 dest) { @@ -344,6 +338,12 @@ glmc_vec3_smoothinterpc(vec3 from, vec3 to, float t, vec3 dest) { glm_vec3_smoothinterpc(from, to, t, dest); } +CGLM_EXPORT +void +glmc_vec3_swizzle(vec3 v, int mask, vec3 dest) { + glm_vec3_swizzle(v, mask, dest); +} + /* ext */ CGLM_EXPORT @@ -442,6 +442,30 @@ glmc_vec3_fract(vec3 v, vec3 dest) { glm_vec3_fract(v, dest); } +CGLM_EXPORT +void +glmc_vec3_floor(vec3 v, vec3 dest) { + glm_vec3_floor(v, dest); +} + +CGLM_EXPORT +void +glmc_vec3_mods(vec3 v, float s, vec3 dest) { + glm_vec3_mods(v, s, dest); +} + +CGLM_EXPORT +void +glmc_vec3_steps(float edge, vec3 v, vec3 dest) { + glm_vec3_steps(edge, v, dest); +} + +CGLM_EXPORT +void +glmc_vec3_stepr(vec3 edge, float v, vec3 dest) { + glm_vec3_stepr(edge, v, dest); +} + CGLM_EXPORT float glmc_vec3_hadd(vec3 v) { diff --git a/src/vec4.c b/src/vec4.c index cac6606..4b08abf 100644 --- a/src/vec4.c +++ b/src/vec4.c @@ -266,12 +266,6 @@ glmc_vec4_lerpc(vec4 from, vec4 to, float t, vec4 dest) { glm_vec4_lerpc(from, to, t, dest); } -CGLM_EXPORT -void -glmc_vec4_step_uni(float edge, vec4 x, vec4 dest) { - glm_vec4_step_uni(edge, x, dest); -} - CGLM_EXPORT void glmc_vec4_step(vec4 edge, vec4 x, vec4 dest) { @@ -308,6 +302,12 @@ glmc_vec4_cubic(float s, vec4 dest) { glm_vec4_cubic(s, dest); } +CGLM_EXPORT +void +glmc_vec4_swizzle(vec4 v, int mask, vec4 dest) { + glm_vec4_swizzle(v, mask, dest); +} + /* ext */ CGLM_EXPORT @@ -406,6 +406,30 @@ glmc_vec4_fract(vec4 v, vec4 dest) { glm_vec4_fract(v, dest); } +CGLM_EXPORT +void +glmc_vec4_floor(vec4 v, vec4 dest) { + glm_vec4_floor(v, dest); +} + +CGLM_EXPORT +void +glmc_vec4_mods(vec4 v, float s, vec4 dest) { + glm_vec4_mods(v, s, dest); +} + +CGLM_EXPORT +void +glmc_vec4_steps(float edge, vec4 v, vec4 dest) { + glm_vec4_steps(edge, v, dest); +} + +CGLM_EXPORT +void +glmc_vec4_stepr(vec4 edge, float v, vec4 dest) { + glm_vec4_stepr(edge, v, dest); +} + CGLM_EXPORT float glmc_vec4_hadd(vec4 v) { diff --git a/test/include/common.h b/test/include/common.h index cdeede2..1b03f34 100644 --- a/test/include/common.h +++ b/test/include/common.h @@ -106,7 +106,7 @@ typedef struct test_entry_t { #define TEST_IMPL_ARG3(arg1, arg2, arg3, ...) arg3 #define TEST_IMPL_CHOOSER(...) \ - EXPAND(TEST_IMPL_ARG3(__VA_ARGS__, TEST_IMPL_ARG2, TEST_IMPL_ARG1)) + EXPAND(TEST_IMPL_ARG3(__VA_ARGS__, TEST_IMPL_ARG2, TEST_IMPL_ARG1,)) #define TEST_IMPL(...) EXPAND(TEST_IMPL_CHOOSER(__VA_ARGS__)(__VA_ARGS__)) @@ -127,7 +127,7 @@ typedef struct test_entry_t { #define ASSERT_ARG2(expr, msg) ASSERT_EXT(expr, msg) #define ASSERT_ARG3(arg1, arg2, arg3, ...) arg3 -#define ASSERT_CHOOSER(...) ASSERT_ARG3(__VA_ARGS__, ASSERT_ARG2, ASSERT_ARG1) +#define ASSERT_CHOOSER(...) ASSERT_ARG3(__VA_ARGS__, ASSERT_ARG2, ASSERT_ARG1,) #define ASSERT(...) do { ASSERT_CHOOSER(__VA_ARGS__)(__VA_ARGS__) } while(0); #define ASSERTIFY(expr) do { \ test_status_t ts; \ diff --git a/test/src/test_aabb2d.h b/test/src/test_aabb2d.h new file mode 100644 index 0000000..d2ce9fc --- /dev/null +++ b/test/src/test_aabb2d.h @@ -0,0 +1,28 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#include "test_common.h" + +#ifndef CGLM_TEST_AABB2D_ONCE +#define CGLM_TEST_AABB2D_ONCE + +/* Macros */ +/* Deprecated */ + +#endif /* CGLM_TEST_VEC4_ONCE */ + +/* --- */ +TEST_IMPL(GLM_PREFIX, aabb2d_sizev) { + vec2 a[2] = {{10.0f, 10.0f}, {20.0f, 20.0f}}; + vec2 size = {0}; + + GLM(aabb2d_sizev)(a, size); + + ASSERTIFY(test_assert_vec2_eq(size, (vec2){10.0f, 10.0f})) + + TEST_SUCCESS +} diff --git a/test/src/test_euler_to_quat_lh.h b/test/src/test_euler_to_quat_lh.h index faec48e..d4351b0 100644 --- a/test/src/test_euler_to_quat_lh.h +++ b/test/src/test_euler_to_quat_lh.h @@ -491,5 +491,3 @@ TEST_IMPL(GLM_PREFIX, euler_zyx_quat_lh) { } TEST_SUCCESS } - - diff --git a/test/src/test_euler_to_quat_rh.h b/test/src/test_euler_to_quat_rh.h index 221192e..6140a6b 100644 --- a/test/src/test_euler_to_quat_rh.h +++ b/test/src/test_euler_to_quat_rh.h @@ -571,5 +571,3 @@ TEST_IMPL(GLM_PREFIX, euler_zyx_quat_rh) { } TEST_SUCCESS } - - diff --git a/test/src/test_noise.h b/test/src/test_noise.h new file mode 100644 index 0000000..cc7ea3c --- /dev/null +++ b/test/src/test_noise.h @@ -0,0 +1,118 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#include "test_common.h" + +TEST_IMPL(GLM_PREFIX, perlin_vec4) { + vec4 p1[] = { + {0.1f, 0.2f, 0.3f, 0.4f}, + {0.2f, 0.3f, 0.4f, 0.5f}, + {0.3f, 0.4f, 0.5f, 0.6f}, + {0.4f, 0.5f, 0.6f, 0.7f}, + {0.5f, 0.6f, 0.7f, 0.8f}, + {0.6f, 0.7f, 0.8f, 0.9f}, + {0.7f, 0.8f, 0.9f, 1.0f}, + {0.8f, 0.9f, 1.0f, 1.1f}, + {0.9f, 1.0f, 1.1f, 1.2f}, + {1.0f, 1.1f, 1.2f, 1.3f}, + }; + + /* expected values calculated by glm::perlin */ + float e[] = { + -0.5091819763183594f, + -0.4375732541084290f, + -0.3212279379367828f, + -0.2279999703168869f, + -0.1577337533235550f, + -0.0445968918502331f, + 0.1069696992635727f, + 0.2067739963531494f, + 0.2106968611478806f, + 0.1397782564163208f + }; + + for (int i = 0; i < 10; i++) { + ASSERT(test_eq(GLM(perlin_vec4)(p1[i]), e[i])); + } + + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, perlin_vec3) { + vec3 p1[] = { + {0.1f, 0.2f, 0.3f}, + {0.2f, 0.3f, 0.4f}, + {0.3f, 0.4f, 0.5f}, + {0.4f, 0.5f, 0.6f}, + {0.5f, 0.6f, 0.7f}, + {0.6f, 0.7f, 0.8f}, + {0.7f, 0.8f, 0.9f}, + {0.8f, 0.9f, 1.0f}, + {0.9f, 1.0f, 1.1f}, + {1.0f, 1.1f, 1.2f}, + }; + + /* expected values calculated by glm::perlin */ + float e[] = { + -0.2909241318702698f, + -0.4667602181434631f, + -0.4679279625415802f, + -0.2616460621356964f, + 0.0562822706997395f, + 0.3178773224353790f, + 0.3981811404228210f, + 0.3011017739772797f, + 0.1263920217752457f, + -0.0602480024099350f + }; + + for (int i = 0; i < 10; i++) { + ASSERT(test_eq(GLM(perlin_vec3)(p1[i]), e[i])); + } + + TEST_SUCCESS +} + + +TEST_IMPL(GLM_PREFIX, perlin_vec2) { + vec2 p1[] = { + {0.1f, 0.2f}, + {0.2f, 0.3f}, + {0.3f, 0.4f}, + {0.4f, 0.5f}, + {0.5f, 0.6f}, + {0.6f, 0.7f}, + {0.7f, 0.8f}, + {0.8f, 0.9f}, + {0.9f, 1.0f}, + {1.0f, 1.1f}, + }; + + /* expected values calculated by glm::perlin */ + float e[] = { + 0.2841092348098755f, + 0.2328013032674789f, + -0.0017980185803026f, + -0.3300299644470215f, + -0.5998955368995667f, + -0.6914522647857666f, + -0.5896517634391785f, + -0.3778679668903351f, + -0.1557840555906296f, + 0.0453133136034012f + }; + + for (int i = 0; i < 10; i++) { + ASSERT(test_eq(GLM(perlin_vec2)(p1[i]), e[i])); + } + + TEST_SUCCESS +} + + + + diff --git a/test/src/test_ray.h b/test/src/test_ray.h index 6f2bec5..ac47685 100644 --- a/test/src/test_ray.h +++ b/test/src/test_ray.h @@ -71,4 +71,3 @@ TEST_IMPL(GLM_PREFIX, ray_at) { TEST_SUCCESS } - diff --git a/test/src/test_vec2.h b/test/src/test_vec2.h index e7bfe88..026c387 100644 --- a/test/src/test_vec2.h +++ b/test/src/test_vec2.h @@ -688,6 +688,70 @@ TEST_IMPL(GLM_PREFIX, vec2_abs) { TEST_SUCCESS } +TEST_IMPL(GLM_PREFIX, vec2_fract) { + vec2 v1 = {2.104f, 3.012f}, v2 = {12.35f, 31.140f}, v3, v4; + vec2 v5 = {0.104f, 0.012f}, v6 = {0.35f, 0.140f}; + + GLM(vec2_fract)(v1, v3); + GLM(vec2_fract)(v2, v4); + + ASSERTIFY(test_assert_vec2_eq(v3, v5)) + ASSERTIFY(test_assert_vec2_eq(v4, v6)) + + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, vec2_floor) { + vec2 v1 = {2.104f, 3.012f}, v2 = {12.35f, 31.140f}, v3, v4; + vec2 v5 = {2.0f, 3.0f}, v6 = {12.0f, 31.0f}; + + GLM(vec2_floor)(v1, v3); + GLM(vec2_floor)(v2, v4); + + ASSERTIFY(test_assert_vec2_eq(v3, v5)) + ASSERTIFY(test_assert_vec2_eq(v4, v6)) + + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, vec2_mods) { + vec2 v1 = {2.104f, 3.012f}, v2 = {12.35f, 31.140f}, v3, v4; + vec2 v5 = {0.104f, 0.012f}, v6 = {0.35f, 0.140f}; + + /* Mod 1 - leaves just the fractional part */ + GLM(vec2_mods)(v1, 1.0f, v3); + GLM(vec2_mods)(v2, 1.0f, v4); + + ASSERTIFY(test_assert_vec2_eq(v3, v5)) + ASSERTIFY(test_assert_vec2_eq(v4, v6)) + + /* Mod 2 - parity + fractional part */ + GLM(vec2_mods)(v1, 2.0f, v3); + GLM(vec2_mods)(v2, 2.0f, v4); + + vec2 v7 = {0.104f, 1.012f}, v8 = {0.35f, 1.140f}; + + ASSERTIFY(test_assert_vec2_eq(v3, v7)) + ASSERTIFY(test_assert_vec2_eq(v4, v8)) + + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, vec2_swizzle) { + vec2 v; + + v[0] = 1; + v[1] = 2; + + GLM(vec2_swizzle)(v, GLM_SHUFFLE2(1, 0), v); + ASSERTIFY(test_assert_vec2_eq(v, (vec2){2, 1})) + + GLM(vec2_swizzle)(v, GLM_SHUFFLE2(0, 0), v); + ASSERTIFY(test_assert_vec2_eq(v, (vec2){1, 1})) + + TEST_SUCCESS +} + TEST_IMPL(GLM_PREFIX, vec2_lerp) { vec2 v1 = {-100.0f, -200.0f}; vec2 v2 = {100.0f, 200.0f}; @@ -704,6 +768,66 @@ TEST_IMPL(GLM_PREFIX, vec2_lerp) { TEST_SUCCESS } +TEST_IMPL(GLM_PREFIX, vec2_steps) { + vec2 v1 = {-100.0f, -200.0f}; + vec2 v2; + + GLM(vec2_steps)(-2.5f, v1, v2); + ASSERT(test_eq(v2[0], 0.0f)) + ASSERT(test_eq(v2[1], 0.0f)) + + GLM(vec2_steps)(-150.0f, v1, v2); + ASSERT(test_eq(v2[0], 1.0f)) + ASSERT(test_eq(v2[1], 0.0f)) + + GLM(vec2_steps)(-300.0f, v1, v2); + ASSERT(test_eq(v2[0], 1.0f)) + ASSERT(test_eq(v2[1], 1.0f)) + + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, vec2_stepr) { + vec2 v1 = {-2.5f, -150.0f}; + vec2 v2; + + GLM(vec2_stepr)(v1, -200.0f, v2); + ASSERT(test_eq(v2[0], 0.0f)) + ASSERT(test_eq(v2[1], 0.0f)) + + GLM(vec2_stepr)(v1, -150.0f, v2); + ASSERT(test_eq(v2[0], 0.0f)) + ASSERT(test_eq(v2[1], 1.0f)) + + GLM(vec2_stepr)(v1, 0.0f, v2); + ASSERT(test_eq(v2[0], 1.0f)) + ASSERT(test_eq(v2[1], 1.0f)) + + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, vec2_step) { + vec2 v1 = {-100.0f, -200.0f}; + vec2 s1 = {-100.0f, 0.0f}; + vec2 s2 = {100.0f, -220.0f}; + vec2 s3 = {100.0f, 200.0f}; + vec2 v2; + + GLM(vec2_step)(s1, v1, v2); + ASSERT(test_eq(v2[0], 1.0f)) + ASSERT(test_eq(v2[1], 0.0f)) + + GLM(vec2_step)(s2, v1, v2); + ASSERT(test_eq(v2[0], 0.0f)) + ASSERT(test_eq(v2[1], 1.0f)) + + GLM(vec2_step)(s3, v1, v2); + ASSERT(test_eq(v2[0], 0.0f)) + ASSERT(test_eq(v2[1], 0.0f)) + + TEST_SUCCESS +} + TEST_IMPL(GLM_PREFIX, vec2_complex_mul) { vec2 v1 = { 3.0f, 5.0f }, v2 = { 7.0f, 11.0f }, @@ -792,7 +916,7 @@ TEST_IMPL(GLM_PREFIX, vec2_refract) { r = GLM(vec2_refract)(v, N, eta, dest); // In 2D, we expect a similar bending behavior as in 3D, so we check dest[1] if (!(dest[0] == 0.0f && dest[1] == 0.0f)) { - ASSERT(dest[1] < -sqrtf(0.5f)); // Refracted ray bends away from the normal + ASSERT(dest[1] < -0.3f); // Refracted ray bends away from the normal ASSERT(r == true); } else { ASSERT(dest[0] == 0.0f && dest[1] == 0.0f); // Total internal reflection @@ -809,7 +933,7 @@ TEST_IMPL(GLM_PREFIX, vec2_refract) { eta = 1.5f / 1.33f; r = GLM(vec2_refract)(v, N, eta, dest); ASSERT(r == true); - ASSERT(dest[1] < -sqrtf(0.5f)); // Expect bending towards the normal, less bending than air to glass + ASSERT(dest[1] < -0.6f); // Expect bending towards the normal, less bending than air to glass /* Diamond to Air (eta = 2.42 / 1.0) */ eta = 2.42f / 1.0f; @@ -825,4 +949,3 @@ TEST_IMPL(GLM_PREFIX, vec2_refract) { TEST_SUCCESS } - diff --git a/test/src/test_vec3.h b/test/src/test_vec3.h index 7c057f3..4d963d5 100644 --- a/test/src/test_vec3.h +++ b/test/src/test_vec3.h @@ -872,18 +872,30 @@ TEST_IMPL(GLM_PREFIX, vec3_angle) { float a; a = GLM(vec3_angle)(v1, v1); + +#ifndef CGLM_FAST_MATH ASSERT(!isinf(a)) ASSERT(!isnan(a)) +#endif + ASSERT(test_eq(a, 0.0f)) a = GLM(vec3_angle)(v1, v2); + +#ifndef CGLM_FAST_MATH ASSERT(!isinf(a)) ASSERT(!isnan(a)) +#endif + ASSERT(test_eq(a, GLM_PI_4f)) a = GLM(vec3_angle)(v1, v3); + +#ifndef CGLM_FAST_MATH ASSERT(!isinf(a)) ASSERT(!isnan(a)) +#endif + ASSERT(test_eq(a, GLM_PI_2f)) TEST_SUCCESS @@ -1227,23 +1239,39 @@ TEST_IMPL(GLM_PREFIX, vec3_ortho) { GLM(vec3_ortho)(v4, v8); a = glm_vec3_angle(v1, v5); + +#ifndef CGLM_FAST_MATH ASSERT(!isinf(a)) ASSERT(!isnan(a)) +#endif + ASSERT(test_eq(a, GLM_PI_2f)) a = glm_vec3_angle(v2, v6); + +#ifndef CGLM_FAST_MATH ASSERT(!isinf(a)) ASSERT(!isnan(a)) +#endif + ASSERT(test_eq(a, GLM_PI_2f)) a = glm_vec3_angle(v3, v7); + +#ifndef CGLM_FAST_MATH ASSERT(!isinf(a)) ASSERT(!isnan(a)) +#endif + ASSERT(test_eq(a, GLM_PI_2f)) a = glm_vec3_angle(v4, v8); + +#ifndef CGLM_FAST_MATH ASSERT(!isinf(a)) ASSERT(!isnan(a)) +#endif + ASSERT(test_eq(a, GLM_PI_2f)) TEST_SUCCESS @@ -1365,21 +1393,43 @@ TEST_IMPL(GLM_PREFIX, vec3_mixc) { TEST_SUCCESS } -TEST_IMPL(GLM_PREFIX, vec3_step_uni) { +TEST_IMPL(GLM_PREFIX, vec3_steps) { vec3 v1 = {-100.0f, -200.0f, -10.0f}; vec3 v2; - GLM(vec3_step_uni)(-2.5f, v1, v2); + GLM(vec3_steps)(-2.5f, v1, v2); ASSERT(test_eq(v2[0], 0.0f)) ASSERT(test_eq(v2[1], 0.0f)) ASSERT(test_eq(v2[2], 0.0f)) - GLM(vec3_step_uni)(-10.0f, v1, v2); + GLM(vec3_steps)(-10.0f, v1, v2); ASSERT(test_eq(v2[0], 0.0f)) ASSERT(test_eq(v2[1], 0.0f)) ASSERT(test_eq(v2[2], 1.0f)) - GLM(vec3_step_uni)(-1000.0f, v1, v2); + GLM(vec3_steps)(-1000.0f, v1, v2); + ASSERT(test_eq(v2[0], 1.0f)) + ASSERT(test_eq(v2[1], 1.0f)) + ASSERT(test_eq(v2[2], 1.0f)) + + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, vec3_stepr) { + vec3 v1 = {-2.5f, -10.0f, -1000.0f}; + vec3 v2; + + GLM(vec3_stepr)(v1, -100.0f, v2); + ASSERT(test_eq(v2[0], 0.0f)) + ASSERT(test_eq(v2[1], 0.0f)) + ASSERT(test_eq(v2[2], 1.0f)) + + GLM(vec3_stepr)(v1, -5.0f, v2); + ASSERT(test_eq(v2[0], 0.0f)) + ASSERT(test_eq(v2[1], 1.0f)) + ASSERT(test_eq(v2[2], 1.0f)) + + GLM(vec3_stepr)(v1, -1.0f, v2); ASSERT(test_eq(v2[0], 1.0f)) ASSERT(test_eq(v2[1], 1.0f)) ASSERT(test_eq(v2[2], 1.0f)) @@ -1524,24 +1574,24 @@ TEST_IMPL(GLM_PREFIX, vec3_swizzle) { v[1] = 2; v[2] = 3; - glm_vec3_swizzle(v, GLM_ZYX, v); + GLM(vec3_swizzle)(v, GLM_ZYX, v); ASSERTIFY(test_assert_vec3_eq(v, (vec3){3, 2, 1})) - glm_vec3_swizzle(v, GLM_XXX, v); + GLM(vec3_swizzle)(v, GLM_XXX, v); ASSERTIFY(test_assert_vec3_eq(v, (vec3){3, 3, 3})) v[0] = 1; v[1] = 2; v[2] = 3; - glm_vec3_swizzle(v, GLM_YYY, v); + GLM(vec3_swizzle)(v, GLM_YYY, v); ASSERTIFY(test_assert_vec3_eq(v, (vec3){2, 2, 2})) v[0] = 1; v[1] = 2; v[2] = 3; - glm_vec3_swizzle(v, GLM_ZZZ, v); + GLM(vec3_swizzle)(v, GLM_ZZZ, v); ASSERTIFY(test_assert_vec3_eq(v, (vec3){3, 3, 3})) TEST_SUCCESS @@ -1673,7 +1723,9 @@ TEST_IMPL(GLM_PREFIX, vec3_eqv_eps) { TEST_IMPL(GLM_PREFIX, vec3_max) { vec3 v1 = {2.104f, -3.012f, -4.10f}, v2 = {-12.35f, -31.140f, -43.502f}; +#ifndef CGLM_FAST_MATH vec3 v3 = {INFINITY, 0.0f, 0.0f}/*, v4 = {NAN, INFINITY, 2.0f}*/; +#endif vec3 /*v5 = {NAN, -1.0f, -1.0f}, */v6 = {-1.0f, -11.0f, 11.0f}; ASSERT(test_eq(GLM(vec3_max)(v1), 2.104f)) @@ -1690,12 +1742,16 @@ TEST_IMPL(GLM_PREFIX, vec3_max) { TEST_IMPL(GLM_PREFIX, vec3_min) { vec3 v1 = {2.104f, -3.012f, -4.10f}, v2 = {-12.35f, -31.140f, -43.502f}; +#ifndef CGLM_FAST_MATH vec3 v3 = {INFINITY, 0.0f, 0.0f}/*, v4 = {NAN, INFINITY, 2.0f}*/; +#endif vec3 /*v5 = {NAN, -1.0f, -1.0f},*/ v6 = {-1.0f, -11.0f, 11.0f}; ASSERT(test_eq(GLM(vec3_min)(v1), -4.10f)) ASSERT(test_eq(GLM(vec3_min)(v2), -43.502f)) +#ifndef CGLM_FAST_MATH ASSERT(test_eq(GLM(vec3_min)(v3), 0.0f)) +#endif // ASSERT(isnan(GLM(vec3_min)(v4))) // ASSERT(isnan(GLM(vec3_min)(v5))) ASSERT(test_eq(GLM(vec3_min)(v6), -11.0f)) @@ -1792,6 +1848,42 @@ TEST_IMPL(GLM_PREFIX, vec3_fract) { TEST_SUCCESS } +TEST_IMPL(GLM_PREFIX, vec3_floor) { + vec3 v1 = {2.104f, 3.012f, 4.10f}, v2 = {12.35f, 31.140f, 43.502f}, v3, v4; + vec3 v5 = {2.0f, 3.0f, 4.0f}, v6 = {12.0f, 31.0f, 43.0f}; + + GLM(vec3_floor)(v1, v3); + GLM(vec3_floor)(v2, v4); + + ASSERTIFY(test_assert_vec3_eq(v3, v5)) + ASSERTIFY(test_assert_vec3_eq(v4, v6)) + + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, vec3_mods) { + vec3 v1 = {2.104f, 3.012f, 4.10f}, v2 = {12.35f, 31.140f, 43.502f}, v3, v4; + vec3 v5 = {0.104f, 0.012f, 0.10f}, v6 = {0.35f, 0.140f, 0.502f}; + + /* Mod 1 - leaves just the fractional part */ + GLM(vec3_mods)(v1, 1.0f, v3); + GLM(vec3_mods)(v2, 1.0f, v4); + + ASSERTIFY(test_assert_vec3_eq(v3, v5)) + ASSERTIFY(test_assert_vec3_eq(v4, v6)) + + /* Mod 2 - parity + fractional part */ + GLM(vec3_mods)(v1, 2.0f, v3); + GLM(vec3_mods)(v2, 2.0f, v4); + + vec3 v7 = {0.104f, 1.012f, 0.10f}, v8 = {0.35f, 1.140f, 1.502f}; + + ASSERTIFY(test_assert_vec3_eq(v3, v7)) + ASSERTIFY(test_assert_vec3_eq(v4, v8)) + + TEST_SUCCESS +} + TEST_IMPL(GLM_PREFIX, vec3_hadd) { vec3 v1 = {2.0f, 3.0f, 4.0f}, v2 = {12.0f, 31.0f, 43.0f}; float r1, r2, r3, r4; @@ -1901,7 +1993,7 @@ TEST_IMPL(GLM_PREFIX, vec3_refract) { eta = 1.33f / 1.0f; r = GLM(vec3_refract)(v, N, eta, dest); if (!(dest[0] == 0.0f && dest[1] == 0.0f && dest[2] == 0.0f)) { - ASSERT(dest[1] < -sqrtf(0.5f)); + ASSERT(dest[1] < -0.3f); ASSERT(r == true); } else { ASSERT(dest[0] == 0.0f && dest[1] == 0.0f && dest[2] == 0.0f); @@ -1922,7 +2014,7 @@ TEST_IMPL(GLM_PREFIX, vec3_refract) { /* Expect bending towards the normal, less bending than air to glass */ ASSERT(r == true); - ASSERT(dest[1] < -sqrtf(0.5f)); + ASSERT(dest[1] < -0.6f); /* Diamond to Air (eta = 2.42 / 1.0) */ eta = 2.42f / 1.0f; diff --git a/test/src/test_vec4.h b/test/src/test_vec4.h index 435c700..417babb 100644 --- a/test/src/test_vec4.h +++ b/test/src/test_vec4.h @@ -980,23 +980,60 @@ TEST_IMPL(GLM_PREFIX, vec4_mixc) { TEST_SUCCESS } -TEST_IMPL(GLM_PREFIX, vec4_step_uni) { +TEST_IMPL(GLM_PREFIX, vec4_steps) { vec4 v1 = {-100.0f, -200.0f, -10.0f, -10.0f}; vec4 v2; - GLM(vec4_step_uni)(-2.5f, v1, v2); + GLM(vec4_steps)(-2.5f, v1, v2); ASSERT(test_eq(v2[0], 0.0f)) ASSERT(test_eq(v2[1], 0.0f)) ASSERT(test_eq(v2[2], 0.0f)) ASSERT(test_eq(v2[3], 0.0f)) - GLM(vec4_step_uni)(-10.0f, v1, v2); + GLM(vec4_steps)(-10.0f, v1, v2); ASSERT(test_eq(v2[0], 0.0f)) ASSERT(test_eq(v2[1], 0.0f)) ASSERT(test_eq(v2[2], 1.0f)) ASSERT(test_eq(v2[3], 1.0f)) - GLM(vec4_step_uni)(-1000.0f, v1, v2); + GLM(vec4_steps)(-1000.0f, v1, v2); + ASSERT(test_eq(v2[0], 1.0f)) + ASSERT(test_eq(v2[1], 1.0f)) + ASSERT(test_eq(v2[2], 1.0f)) + ASSERT(test_eq(v2[3], 1.0f)) + + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, vec4_stepr) { + vec4 v1 = {-2.5f, -100.0f, -200.0f, -300.0f}; + vec4 v2; + + GLM(vec4_stepr)(v1, -1000.0f, v2); + ASSERT(test_eq(v2[0], 0.0f)) + ASSERT(test_eq(v2[1], 0.0f)) + ASSERT(test_eq(v2[2], 0.0f)) + ASSERT(test_eq(v2[3], 0.0f)) + + GLM(vec4_stepr)(v1, -250.0f, v2); + ASSERT(test_eq(v2[0], 0.0f)) + ASSERT(test_eq(v2[1], 0.0f)) + ASSERT(test_eq(v2[2], 0.0f)) + ASSERT(test_eq(v2[3], 1.0f)) + + GLM(vec4_stepr)(v1, -150.0f, v2); + ASSERT(test_eq(v2[0], 0.0f)) + ASSERT(test_eq(v2[1], 0.0f)) + ASSERT(test_eq(v2[2], 1.0f)) + ASSERT(test_eq(v2[3], 1.0f)) + + GLM(vec4_stepr)(v1, -10.0f, v2); + ASSERT(test_eq(v2[0], 0.0f)) + ASSERT(test_eq(v2[1], 1.0f)) + ASSERT(test_eq(v2[2], 1.0f)) + ASSERT(test_eq(v2[3], 1.0f)) + + GLM(vec4_stepr)(v1, 0.0f, v2); ASSERT(test_eq(v2[0], 1.0f)) ASSERT(test_eq(v2[1], 1.0f)) ASSERT(test_eq(v2[2], 1.0f)) @@ -1184,10 +1221,10 @@ TEST_IMPL(GLM_PREFIX, vec4_swizzle) { v[2] = 3; v[3] = 4; - glm_vec4_swizzle(v, GLM_WZYX, v); + GLM(vec4_swizzle)(v, GLM_WZYX, v); ASSERTIFY(test_assert_vec4_eq(v, (vec4){4, 3, 2, 1})) - glm_vec4_swizzle(v, GLM_XXXX, v); + GLM(vec4_swizzle)(v, GLM_XXXX, v); ASSERTIFY(test_assert_vec4_eq(v, (vec4){4, 4, 4, 4})) v[0] = 1; @@ -1195,7 +1232,7 @@ TEST_IMPL(GLM_PREFIX, vec4_swizzle) { v[2] = 3; v[3] = 4; - glm_vec4_swizzle(v, GLM_YYYY, v); + GLM(vec4_swizzle)(v, GLM_YYYY, v); ASSERTIFY(test_assert_vec4_eq(v, (vec4){2, 2, 2, 2})) v[0] = 1; @@ -1203,7 +1240,7 @@ TEST_IMPL(GLM_PREFIX, vec4_swizzle) { v[2] = 3; v[3] = 4; - glm_vec4_swizzle(v, GLM_ZZZZ, v); + GLM(vec4_swizzle)(v, GLM_ZZZZ, v); ASSERTIFY(test_assert_vec4_eq(v, (vec4){3, 3, 3, 3})) v[0] = 1; @@ -1211,7 +1248,7 @@ TEST_IMPL(GLM_PREFIX, vec4_swizzle) { v[2] = 3; v[3] = 4; - glm_vec4_swizzle(v, GLM_WWWW, v); + GLM(vec4_swizzle)(v, GLM_WWWW, v); ASSERTIFY(test_assert_vec4_eq(v, (vec4){4, 4, 4, 4})) TEST_SUCCESS @@ -1344,7 +1381,9 @@ TEST_IMPL(GLM_PREFIX, vec4_eqv_eps) { TEST_IMPL(GLM_PREFIX, vec4_max) { vec4 v1 = {2.104f, -3.012f, -4.10f, -4.10f}; vec4 v2 = {-12.35f, -31.140f, -43.502f, -43.502f}; +#ifndef CGLM_FAST_MATH vec4 v3 = {INFINITY, 0.0f, 0.0f, 0.0f}; +#endif // vec4 v4 = {NAN, INFINITY, 2.0f, 2.0f}; // vec4 v5 = {NAN, -1.0f, -1.0f, -1.0f}; vec4 v6 = {-1.0f, -11.0f, 11.0f, 11.0f}; @@ -1364,14 +1403,18 @@ TEST_IMPL(GLM_PREFIX, vec4_max) { TEST_IMPL(GLM_PREFIX, vec4_min) { vec4 v1 = {2.104f, -3.012f, -4.10f, -4.10f}; vec4 v2 = {-12.35f, -31.140f, -43.502f, -43.502f}; +#ifndef CGLM_FAST_MATH vec4 v3 = {INFINITY, 0.0f, 0.0f, 0.0f}; +#endif // vec4 v4 = {NAN, INFINITY, 2.0f, 2.0f}; // vec4 v5 = {NAN, -1.0f, -1.0f, -1.0f}; vec4 v6 = {-1.0f, -11.0f, 11.0f, 11.0f}; ASSERT(test_eq(GLM(vec4_min)(v1), -4.10f)) ASSERT(test_eq(GLM(vec4_min)(v2), -43.502f)) +#ifndef CGLM_FAST_MATH ASSERT(test_eq(GLM(vec4_min)(v3), 0.0f)) +#endif // ASSERT(isnan(GLM(vec4_min)(v4))) // ASSERT(isnan(GLM(vec4_min)(v5))) ASSERT(test_eq(GLM(vec4_min)(v6), -11.0f)) @@ -1484,6 +1527,47 @@ TEST_IMPL(GLM_PREFIX, vec4_fract) { TEST_SUCCESS } +TEST_IMPL(GLM_PREFIX, vec4_floor) { + vec4 v1 = {2.104f, 3.012f, 4.10f, 4.10f}; + vec4 v2 = {12.35f, 31.140f, 43.502f, 43.502f}; + vec4 v3, v4; + vec4 v5 = {2.0f, 3.0f, 4.0f, 4.0f}; + vec4 v6 = {12.0f, 31.0f, 43.0f, 43.0f}; + + GLM(vec4_floor)(v1, v3); + GLM(vec4_floor)(v2, v4); + + ASSERTIFY(test_assert_vec4_eq(v3, v5)) + ASSERTIFY(test_assert_vec4_eq(v4, v6)) + + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, vec4_mods) { + vec4 v1 = {2.104f, 3.012f, 4.10f, 5.78f}, v2 = {12.35f, 31.140f, 43.502f, 198.999f}; + vec4 v3, v4; + vec4 v5 = {0.104f, 0.012f, 0.10f, 0.78f}, v6 = {0.35f, 0.140f, 0.502f, 0.999f}; + + /* Mod 1 - leaves just the fractional part */ + GLM(vec4_mods)(v1, 1.0f, v3); + GLM(vec4_mods)(v2, 1.0f, v4); + + ASSERTIFY(test_assert_vec4_eq(v3, v5)) + ASSERTIFY(test_assert_vec4_eq(v4, v6)) + + /* Mod 2 - parity + fractional part */ + GLM(vec4_mods)(v1, 2.0f, v3); + GLM(vec4_mods)(v2, 2.0f, v4); + + vec4 v7 = {0.104f, 1.012f, 0.10f, 1.78f}, v8 = {0.35f, 1.140f, 1.502f, 0.999f}; + + ASSERTIFY(test_assert_vec4_eq(v3, v7)) + ASSERTIFY(test_assert_vec4_eq(v4, v8)) + + TEST_SUCCESS +} + + TEST_IMPL(GLM_PREFIX, vec4_hadd) { vec4 v1 = {2.0f, 3.0f, 4.0f, 4.0f}, v2 = {12.0f, 31.0f, 43.0f, 43.0f}; float r1, r2, r3, r4; @@ -1586,7 +1670,7 @@ TEST_IMPL(GLM_PREFIX, vec4_refract) { eta = 1.33f / 1.0f; r = GLM(vec4_refract)(v, N, eta, dest); if (!(dest[0] == 0.0f && dest[1] == 0.0f && dest[2] == 0.0f && dest[3] == 0.0f)) { - ASSERT(dest[1] < -sqrtf(0.5f)); + ASSERT(dest[1] < -0.3f); ASSERT(r == true); } else { ASSERT(dest[0] == 0.0f && dest[1] == 0.0f && dest[2] == 0.0f && dest[3] == 0.0f); @@ -1603,7 +1687,7 @@ TEST_IMPL(GLM_PREFIX, vec4_refract) { eta = 1.5f / 1.33f; r = GLM(vec4_refract)(v, N, eta, dest); ASSERT(r == true); - ASSERT(dest[1] < -sqrtf(0.5f)); // Expect bending towards the normal, less bending than air to glass + ASSERT(dest[1] < -0.6f); // Expect bending towards the normal, less bending than air to glass /* Diamond to Air (eta = 2.42 / 1.0) */ eta = 2.42f / 1.0f; @@ -1619,4 +1703,3 @@ TEST_IMPL(GLM_PREFIX, vec4_refract) { TEST_SUCCESS } - diff --git a/test/src/tests.c b/test/src/tests.c index 4d93294..bc24668 100644 --- a/test/src/tests.c +++ b/test/src/tests.c @@ -30,9 +30,11 @@ #include "test_quat.h" #include "test_project.h" #include "test_plane.h" +#include "test_noise.h" #include "test_affine.h" #include "test_affine2d.h" #include "test_affine_mat.h" +#include "test_aabb2d.h" #include "test_ray.h" #include "test_cam.h" #include "test_cam_lh_no.h" @@ -69,9 +71,11 @@ #include "test_quat.h" #include "test_project.h" #include "test_plane.h" +#include "test_noise.h" #include "test_affine.h" #include "test_affine2d.h" #include "test_affine_mat.h" +#include "test_aabb2d.h" #include "test_ray.h" #include "test_cam.h" #include "test_cam_lh_no.h" diff --git a/test/tests.h b/test/tests.h index bcb2fda..b959ad6 100644 --- a/test/tests.h +++ b/test/tests.h @@ -97,6 +97,9 @@ TEST_DECLARE(glmc_rotate2d_make) TEST_DECLARE(glmc_rotate2d) TEST_DECLARE(glmc_rotate2d_to) +/* aabb2d */ +TEST_DECLARE(glm_aabb2d_sizev) + /* mat4 */ TEST_DECLARE(glm_mat4_ucopy) TEST_DECLARE(glm_mat4_copy) @@ -356,6 +359,14 @@ TEST_DECLARE(glmc_project) TEST_DECLARE(glm_plane_normalize) TEST_DECLARE(glmc_plane_normalize) +/* noise */ +TEST_DECLARE(glm_perlin_vec4) +TEST_DECLARE(glmc_perlin_vec4) +TEST_DECLARE(glm_perlin_vec3) +TEST_DECLARE(glmc_perlin_vec3) +TEST_DECLARE(glm_perlin_vec2) +TEST_DECLARE(glmc_perlin_vec2) + /* utils */ TEST_DECLARE(clamp) @@ -531,6 +542,11 @@ TEST_DECLARE(glm_vec2_maxv) TEST_DECLARE(glm_vec2_minv) TEST_DECLARE(glm_vec2_clamp) TEST_DECLARE(glm_vec2_abs) +TEST_DECLARE(glm_vec2_fract) +TEST_DECLARE(glm_vec2_floor) +TEST_DECLARE(glm_vec2_mods) +TEST_DECLARE(glm_vec2_steps) +TEST_DECLARE(glm_vec2_stepr) TEST_DECLARE(glm_vec2_lerp) TEST_DECLARE(glm_vec2_complex_mul) TEST_DECLARE(glm_vec2_complex_div) @@ -579,6 +595,11 @@ TEST_DECLARE(glmc_vec2_maxv) TEST_DECLARE(glmc_vec2_minv) TEST_DECLARE(glmc_vec2_clamp) TEST_DECLARE(glmc_vec2_abs) +TEST_DECLARE(glmc_vec2_fract) +TEST_DECLARE(glmc_vec2_floor) +TEST_DECLARE(glmc_vec2_mods) +TEST_DECLARE(glmc_vec2_steps) +TEST_DECLARE(glmc_vec2_stepr) TEST_DECLARE(glmc_vec2_lerp) TEST_DECLARE(glmc_vec2_complex_mul) TEST_DECLARE(glmc_vec2_complex_div) @@ -662,7 +683,6 @@ TEST_DECLARE(glm_vec3_ortho) TEST_DECLARE(glm_vec3_clamp) TEST_DECLARE(glm_vec3_mix) TEST_DECLARE(glm_vec3_mixc) -TEST_DECLARE(glm_vec3_step_uni) TEST_DECLARE(glm_vec3_step) TEST_DECLARE(glm_vec3_smoothstep_uni) TEST_DECLARE(glm_vec3_smoothstep) @@ -684,6 +704,10 @@ TEST_DECLARE(glm_vec3_isvalid) TEST_DECLARE(glm_vec3_sign) TEST_DECLARE(glm_vec3_abs) TEST_DECLARE(glm_vec3_fract) +TEST_DECLARE(glm_vec3_floor) +TEST_DECLARE(glm_vec3_mods) +TEST_DECLARE(glm_vec3_steps) +TEST_DECLARE(glm_vec3_stepr) TEST_DECLARE(glm_vec3_hadd) TEST_DECLARE(glm_vec3_sqrt) TEST_DECLARE(glm_vec3_make) @@ -741,7 +765,6 @@ TEST_DECLARE(glmc_vec3_ortho) TEST_DECLARE(glmc_vec3_clamp) TEST_DECLARE(glmc_vec3_mix) TEST_DECLARE(glmc_vec3_mixc) -TEST_DECLARE(glmc_vec3_step_uni) TEST_DECLARE(glmc_vec3_step) TEST_DECLARE(glmc_vec3_smoothstep_uni) TEST_DECLARE(glmc_vec3_smoothstep) @@ -763,6 +786,10 @@ TEST_DECLARE(glmc_vec3_isvalid) TEST_DECLARE(glmc_vec3_sign) TEST_DECLARE(glmc_vec3_abs) TEST_DECLARE(glmc_vec3_fract) +TEST_DECLARE(glmc_vec3_floor) +TEST_DECLARE(glmc_vec3_mods) +TEST_DECLARE(glmc_vec3_steps) +TEST_DECLARE(glmc_vec3_stepr) TEST_DECLARE(glmc_vec3_hadd) TEST_DECLARE(glmc_vec3_sqrt) TEST_DECLARE(glmc_vec3_make) @@ -831,7 +858,6 @@ TEST_DECLARE(glm_vec4_lerp) TEST_DECLARE(glm_vec4_lerpc) TEST_DECLARE(glm_vec4_mix) TEST_DECLARE(glm_vec4_mixc) -TEST_DECLARE(glm_vec4_step_uni) TEST_DECLARE(glm_vec4_step) TEST_DECLARE(glm_vec4_smoothstep_uni) TEST_DECLARE(glm_vec4_smoothstep) @@ -854,6 +880,10 @@ TEST_DECLARE(glm_vec4_isvalid) TEST_DECLARE(glm_vec4_sign) TEST_DECLARE(glm_vec4_abs) TEST_DECLARE(glm_vec4_fract) +TEST_DECLARE(glm_vec4_floor) +TEST_DECLARE(glm_vec4_mods) +TEST_DECLARE(glm_vec4_steps) +TEST_DECLARE(glm_vec4_stepr) TEST_DECLARE(glm_vec4_hadd) TEST_DECLARE(glm_vec4_sqrt) TEST_DECLARE(glm_vec4_make) @@ -905,7 +935,6 @@ TEST_DECLARE(glmc_vec4_lerp) TEST_DECLARE(glmc_vec4_lerpc) TEST_DECLARE(glmc_vec4_mix) TEST_DECLARE(glmc_vec4_mixc) -TEST_DECLARE(glmc_vec4_step_uni) TEST_DECLARE(glmc_vec4_step) TEST_DECLARE(glmc_vec4_smoothstep_uni) TEST_DECLARE(glmc_vec4_smoothstep) @@ -928,6 +957,10 @@ TEST_DECLARE(glmc_vec4_isvalid) TEST_DECLARE(glmc_vec4_sign) TEST_DECLARE(glmc_vec4_abs) TEST_DECLARE(glmc_vec4_fract) +TEST_DECLARE(glmc_vec4_floor) +TEST_DECLARE(glmc_vec4_mods) +TEST_DECLARE(glmc_vec4_steps) +TEST_DECLARE(glmc_vec4_stepr) TEST_DECLARE(glmc_vec4_hadd) TEST_DECLARE(glmc_vec4_sqrt) TEST_DECLARE(glmc_vec4_make) @@ -1274,6 +1307,9 @@ TEST_LIST { TEST_ENTRY(glmc_rotate2d_make) TEST_ENTRY(glmc_rotate2d) TEST_ENTRY(glmc_rotate2d_to) + + /* aabb2d */ + TEST_ENTRY(glm_aabb2d_sizev) /* mat4 */ TEST_ENTRY(glm_mat4_ucopy) @@ -1533,6 +1569,14 @@ TEST_LIST { /* plane */ TEST_ENTRY(glm_plane_normalize) TEST_ENTRY(glmc_plane_normalize) + + /* noise */ + TEST_ENTRY(glm_perlin_vec4) + TEST_ENTRY(glmc_perlin_vec4) + TEST_ENTRY(glm_perlin_vec3) + TEST_ENTRY(glmc_perlin_vec3) + TEST_ENTRY(glm_perlin_vec2) + TEST_ENTRY(glmc_perlin_vec2) /* utils */ TEST_ENTRY(clamp) @@ -1708,6 +1752,12 @@ TEST_LIST { TEST_ENTRY(glm_vec2_maxv) TEST_ENTRY(glm_vec2_minv) TEST_ENTRY(glm_vec2_clamp) + TEST_ENTRY(glm_vec2_abs) + TEST_ENTRY(glm_vec2_fract) + TEST_ENTRY(glm_vec2_floor) + TEST_ENTRY(glm_vec2_mods) + TEST_ENTRY(glm_vec2_steps) + TEST_ENTRY(glm_vec2_stepr) TEST_ENTRY(glm_vec2_lerp) TEST_ENTRY(glm_vec2_complex_mul) TEST_ENTRY(glm_vec2_complex_div) @@ -1756,6 +1806,11 @@ TEST_LIST { TEST_ENTRY(glmc_vec2_minv) TEST_ENTRY(glmc_vec2_clamp) TEST_ENTRY(glmc_vec2_abs) + TEST_ENTRY(glmc_vec2_fract) + TEST_ENTRY(glmc_vec2_floor) + TEST_ENTRY(glmc_vec2_mods) + TEST_ENTRY(glmc_vec2_steps) + TEST_ENTRY(glmc_vec2_stepr) TEST_ENTRY(glmc_vec2_lerp) TEST_ENTRY(glmc_vec2_complex_mul) TEST_ENTRY(glmc_vec2_complex_div) @@ -1838,7 +1893,6 @@ TEST_LIST { TEST_ENTRY(glm_vec3_clamp) TEST_ENTRY(glm_vec3_mix) TEST_ENTRY(glm_vec3_mixc) - TEST_ENTRY(glm_vec3_step_uni) TEST_ENTRY(glm_vec3_step) TEST_ENTRY(glm_vec3_smoothstep_uni) TEST_ENTRY(glm_vec3_smoothstep) @@ -1860,6 +1914,10 @@ TEST_LIST { TEST_ENTRY(glm_vec3_sign) TEST_ENTRY(glm_vec3_abs) TEST_ENTRY(glm_vec3_fract) + TEST_ENTRY(glm_vec3_floor) + TEST_ENTRY(glm_vec3_mods) + TEST_ENTRY(glm_vec3_steps) + TEST_ENTRY(glm_vec3_stepr) TEST_ENTRY(glm_vec3_hadd) TEST_ENTRY(glm_vec3_sqrt) TEST_ENTRY(glm_vec3_make) @@ -1917,7 +1975,6 @@ TEST_LIST { TEST_ENTRY(glmc_vec3_clamp) TEST_ENTRY(glmc_vec3_mix) TEST_ENTRY(glmc_vec3_mixc) - TEST_ENTRY(glmc_vec3_step_uni) TEST_ENTRY(glmc_vec3_step) TEST_ENTRY(glmc_vec3_smoothstep_uni) TEST_ENTRY(glmc_vec3_smoothstep) @@ -1939,6 +1996,10 @@ TEST_LIST { TEST_ENTRY(glmc_vec3_sign) TEST_ENTRY(glmc_vec3_abs) TEST_ENTRY(glmc_vec3_fract) + TEST_ENTRY(glmc_vec3_floor) + TEST_ENTRY(glmc_vec3_mods) + TEST_ENTRY(glmc_vec3_steps) + TEST_ENTRY(glmc_vec3_stepr) TEST_ENTRY(glmc_vec3_hadd) TEST_ENTRY(glmc_vec3_sqrt) TEST_ENTRY(glmc_vec3_make) @@ -2007,7 +2068,6 @@ TEST_LIST { TEST_ENTRY(glm_vec4_lerpc) TEST_ENTRY(glm_vec4_mix) TEST_ENTRY(glm_vec4_mixc) - TEST_ENTRY(glm_vec4_step_uni) TEST_ENTRY(glm_vec4_step) TEST_ENTRY(glm_vec4_smoothstep_uni) TEST_ENTRY(glm_vec4_smoothstep) @@ -2030,6 +2090,10 @@ TEST_LIST { TEST_ENTRY(glm_vec4_sign) TEST_ENTRY(glm_vec4_abs) TEST_ENTRY(glm_vec4_fract) + TEST_ENTRY(glm_vec4_floor) + TEST_ENTRY(glm_vec4_mods) + TEST_ENTRY(glm_vec4_steps) + TEST_ENTRY(glm_vec4_stepr) TEST_ENTRY(glm_vec4_hadd) TEST_ENTRY(glm_vec4_sqrt) TEST_ENTRY(glm_vec4_make) @@ -2081,7 +2145,6 @@ TEST_LIST { TEST_ENTRY(glmc_vec4_lerpc) TEST_ENTRY(glmc_vec4_mix) TEST_ENTRY(glmc_vec4_mixc) - TEST_ENTRY(glmc_vec4_step_uni) TEST_ENTRY(glmc_vec4_step) TEST_ENTRY(glmc_vec4_smoothstep_uni) TEST_ENTRY(glmc_vec4_smoothstep) @@ -2104,6 +2167,10 @@ TEST_LIST { TEST_ENTRY(glmc_vec4_sign) TEST_ENTRY(glmc_vec4_abs) TEST_ENTRY(glmc_vec4_fract) + TEST_ENTRY(glmc_vec4_floor) + TEST_ENTRY(glmc_vec4_mods) + TEST_ENTRY(glmc_vec4_steps) + TEST_ENTRY(glmc_vec4_stepr) TEST_ENTRY(glmc_vec4_hadd) TEST_ENTRY(glmc_vec4_sqrt) TEST_ENTRY(glmc_vec4_make)